instagrapi
instagrapi copied to clipboard
fix for user info (user info gql)
__a=1&__d=dis no longer work , replaced with web_profile_info
While you probably found the correct workaround, this doesn't seem to be compatible with the already existing methods and setup of instagrapi.
@subzeroid (or @tajbowness), as this is a rather important problem, do you possibly have the time to look into fixing this, based on this PR? The solution itself looks pretty easy and just needs to be fit into the existing code base.
While you probably found the correct workaround, this doesn't seem to be compatible with the already existing methods and setup of instagrapi.
@subzeroid (or @tajbowness), as this is a rather important problem, do you possibly have the time to look into fixing this, based on this PR? The solution itself looks pretty easy and just needs to be fit into the existing code base.
What do you mean ? Did you try and got any error ? I tried it and worked for me without any problem, the native public request of Instagrapi uses __a=1 and i bring plane requests to this part to fix it, you can use "extract_gql..." or not, i comment that line, if you use commented line, the result is exactly the same as before, you can easily get user info without need of login
the new endpoint for user info need some new headers and user-agent and the old headers wont work , this is the reason i put headers directly , and instagrapi users wont need to change headers in gql requests like this request , so the better idea is to use headers directly in endpoints like this , understood ?
commented line has been removed. thank you !
I hope, you understand my points. Hardcoding values like this and not relying on existing functions is in general a bad practice (maintainability, generalizability, ...).
I got it that the endpoint probably requires different requests, so in that case, probably the way to go is to generalize the existing functions for the new use cases.
I hope, you understand my points. Hardcoding values like this and not relying on existing functions is in general a bad practice (maintainability, generalizability, ...).
I got it that the endpoint probably requires different requests, so in that case, probably the way to go is to generalize the existing functions for the new use cases.
as i said this is a public request (gql , or non auth request) , and the headers are same everytime you send request , even the current model uses same headers everytime (for public request) ( monitor the instagrapi requests so you can see ) , so instagram will not ban you , rotating headers is for private request ( authenticated requests , my pr is for non authenticated request for user info ) , now do you understand ?
Here, you can see the current setup: https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L209. You can possibly also create a new function there (if needed) and then rely on that one. Please note that there is also already a function for public requests: https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L77.
Here, you can see the current setup:
https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L209
. You can possibly also create a new function there (if needed) and then rely on that one. Please note that there is also already a function for public requests: https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L77
.
this is for __a=1 , they removed that
check the instagrapi gql requests , the headers are same everytime , it uses its own user agent , not logged-in client user agent (mobile), not base_headers , if you use another user agent for this request , it will return you "mismatch user agent error etc"
My main argument stands. Hard coding this like you did is not good practice. Also, there is no error handling for the request.
The already existing functions provide that already. So, I hope, you can find a way how to rely on them (or refactoring them appropriately). I will be of help, if needed.
I meant hard coding like you did. You hard coded this in the wrong place, where it can't be reused. There is no error handling, no reliance on good, already existing functions.
My main argument stands. Hard coding this like you did is not good practice. Also, there is no error handling for the request.
The already existing functions provide that already. So, I hope, you can find a way how to rely on them (or refactoring them appropriately). I will be of help, if needed.
you can see hard-coded by the author in the link below, no problem in public request to hard-code headers
https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L69
thats why i told you to check instagrapi public requests in mitm
thank you for your contribution
(You can also edit GitHub comments, no need to delete and send a new one)
Here, you can see some part of the already existing request error handling code:
https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L190C1-L202C54
So I hope this helps you understand, why it is important to rely on existing functions and why just using requests like you did is not error prone.
the current code which i wrote in my pr will work , however if you mean adding error handling , you can do it by this :
return extract_user_gql(json.loads(cl.public_request(f'https://www.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=headers))['data']['user'])
but the custom headers still needed
Already better. But still needs some more refactoring, from my perspective.
One possible problem now is this line:
https://github.com/subzeroid/instagrapi/blob/b83a00b6d5c23029d9ab22b573ef26ebc79ef262/instagrapi/mixins/public.py#L130C13-L130C48
Not sure, but probably we don't want to update the internal headers with the ones that are only used for that request?
Additionally, probably some more refactoring is sensible (like moving the custom headers to a different place. Defining them here like you do is not really sensible, as it won't allow any other functions to make use of them.).
Not sure, but probably we don't want to update the internal headers with the ones that are only used for that request?\n\nAdditionally, probably some more refactoring is sensible (like moving the custom headers to a different place. Defining them here like you do is not really sensible, as it won't allow any other functions to make use of them.).
Correct we don't need to use these headers on the other methods so make sense to pass them directly to the self.public_request instead of update the headers
Try to have a look at my referenced line again. It shows that if headers are passed to public_request, the headers will then get updated (which is not wanted). So that needs to be slightly refactored, probably.
Try to have a look at my referenced line again. It shows that if headers are passed to
public_request, the headers will then get updated (which is not wanted). So that needs to be slightly refactored, probably.
yeah i got you ,
default_public_headers = self.public.headers
temporary_public_headers = {'Host': 'www.instagram.com','X-Requested-With': 'XMLHttpRequest','Sec-Ch-Prefers-Color-Scheme': 'dark','Sec-Ch-Ua-Platform': '"Linux"','X-Ig-App-Id': '936619743392459','Sec-Ch-Ua-Model': '""','Sec-Ch-Ua-Mobile': '?0','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.112 Safari/537.36','Accept': '*/*','X-Asbd-Id': '129477','Sec-Fetch-Site': 'same-origin','Sec-Fetch-Mode': 'cors','Sec-Fetch-Dest': 'empty','Referer': 'https://www.instagram.com/','Accept-Language': 'en-US,en;q=0.9','Priority': 'u=1, i'}
data = extract_user_gql(json.loads(self.public_request(f'https://www.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=temporary_public_headers))['data']['user'])
self.public.headers.update(default_public_headers)
return data
Your solution fixes the problem, but I think, there is a better way:
Refactoring some functions in public.py.
Why? Because I am rather confident that the headers will be needed for other calls as well in the future. So one possible suggestion would be adding another function similar to public_a1_request in public.py.
That function will have the headers (there, they can probably be hardcoded, then), and it will call public_request in a similar manner, as you showed in your code.
I suggest though, to also refactor public_request and _send_public_request with an additional parameter update_headers=True. Then, you can set this parameter to False in your calls and that will prevent updating the headers in the first place (which seems to be cleaner, compared to setting them first and then reversing that afterwards).
This was kind of what I had in mind all along, and I thought, it was rather obvious, but apparently, my suggestions weren't clear to you, before.
What do you think?
check the changes i made now , i added update_headers=False and i think everything is good now and enough for this step
Thanks, some more nitpicks, though.
@subzeroid, can you give a review and possibly make some calls on discussed topics?
Just add one thing, hardcoding user-agent can lead to auto-detection of the bot on the Instagram-side so I would recommend actually making it exactly the same globally for every request or at least being able to set it as a config variable. Also having that variable (temporary_public_headers) globally available (instead of having it in the user scope) would help if we will have any other request that will need to use it - but that can be tomorrow's problem :)
Just add one thing, hardcoding user-agent can lead to auto-detection of the bot on the Instagram-side so I would recommend actually making it exactly the same globally for every request or at least being able to set it as a config variable. Also having that variable (temporary_public_headers) globally available (instead of having it in the user scope) would help if we will have any other request that will need to use it - but that can be tomorrow's problem :)
Hi, thx for your attention Actually user agent will not be detected .
@SaeidB
Traceback (most recent call last):
File "/Users/mknappe/Projects/inst/instagrapi/test.py", line 2, in <module>
from instagrapi import Client
File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/__init__.py", line 31, in <module>
from instagrapi.mixins.public import (
File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/public.py", line 83
update_headers=None
^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
Forgotten comma on that line.
also:
name 'json' is not defined
Traceback (most recent call last):
File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/user.py", line 194, in user_info_by_username
user = self.user_info_by_username_gql(username)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/user.py", line 146, in user_info_by_username_gql
data = extract_user_gql(json.loads(self.public_request(f'https://www.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=temporary_public_headers))['data']['user'], update_headers=update_headers)
^^^^
NameError: name 'json' is not defined
No Json imported for json.loads
Also:
TypeError: extract_user_gql() got an unexpected keyword argument 'update_headers'
Looks like user.py:147 has a update_headers after () from public request
@SaeidB
Traceback (most recent call last): File "/Users/mknappe/Projects/inst/instagrapi/test.py", line 2, in <module> from instagrapi import Client File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/__init__.py", line 31, in <module> from instagrapi.mixins.public import ( File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/public.py", line 83 update_headers=None ^^^^ SyntaxError: invalid syntax. Perhaps you forgot a comma?Forgotten comma on that line.
also:
name 'json' is not defined Traceback (most recent call last): File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/user.py", line 194, in user_info_by_username user = self.user_info_by_username_gql(username) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/mknappe/Projects/inst/instagrapi/instagrapi/mixins/user.py", line 146, in user_info_by_username_gql data = extract_user_gql(json.loads(self.public_request(f'https://www.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=temporary_public_headers))['data']['user'], update_headers=update_headers) ^^^^ NameError: name 'json' is not definedNo Json imported for json.loads
Also:
TypeError: extract_user_gql() got an unexpected keyword argument 'update_headers'Looks like user.py:147 has a update_headers after () from public request
hi, thanks for the mentioning the missing comma and missing json import has been fixed , for the last issue (unexpected keyword) i think you forgot to update public.py , can you update user.py and public.py and try again ?
@SaeidB Works now, thanks, also I see that there are some conflicts so you need to resolve it before anyone will merge it
Will this fix be merged soon?
Will this fix be merged soon?
hello, i dunno really, but it works and you can add this to your lib even if it didn't merge
The prior pull request still has an issue but this will work: https://github.com/subzeroid/instagrapi/pull/2003