ct0 not in cookies (most likely ip ban)
Lately,
The following error has been appearing to me when I try to log in using twscrape login_accounts.
2024-08-14 12:15:33.159 | ERROR | twscrape.accounts_pool:login:165 - Failed to login 'XAccount': ct0 not in cookies (most likely ip ban)
When I logged in to the account I found out it wasn't blocked.
I have solved that issue for some accounts by logging in manually and then removing the accounts from the database using twscrape del_accounts XAccount .... Then log in to the account manually. Then add the account using twscrape add_accounts ..., then try re-login again using twscrape relogin XAccount ....
It solved the issue for me, but I have to do that manually whenever I face it again. Can we consider automating that?
I have found out that sometimes Twitter requests the email in the middle of your login even if you typed the account name. Maybe that's something new to the Twitter login process.
I don't know exactly if that's an issue with me or with the login process. But I am here to learn.
A note: it takes time from logging in manually to twscrape accepting the login, about 15 minutes.
Guys I found the solution
Go to <your venv or python installation>/site-packages/twscrape/login.py around line 264 in the function async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: after client.headers["x-guest-token"] = guest_token, add a new line client.headers["x-client-transaction-id"] = <your client transaction id>
The complete function looks like this:
async def login(acc: Account, cfg: LoginConfig | None = None) -> Account:
log_id = f"{acc.username} - {acc.email}"
if acc.active:
logger.info(f"account already active {log_id}")
return acc
cfg, imap = cfg or LoginConfig(), None
if cfg.email_first and not cfg.manual:
imap = await imap_login(acc.email, acc.email_password)
async with acc.make_client() as client:
guest_token = await get_guest_token(client)
client.headers["x-guest-token"] = guest_token
client.headers["x-client-transaction-id"] = "<a base64 string>"
rep = await login_initiate(client)
ctx = TaskCtx(client, acc, cfg, None, imap)
print("-------------------")
print(rep.content)
print()
while True:
rep = await next_login_task(ctx, rep)
print(rep.content if rep else "No response")
print()
if not rep:
break
assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)"
client.headers["x-csrf-token"] = client.cookies["ct0"]
client.headers["x-twitter-auth-type"] = "OAuth2Session"
acc.active = True
acc.headers = {k: v for k, v in client.headers.items()}
acc.cookies = {k: v for k, v in client.cookies.items()}
return acc
To obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
Guys I found the solution
Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
Forgot to mention I added a few print statements for debugging purposes. These print statements shouldn't affect the functionality and can be ignored
@frameartist Thanks for sharing your finding! I also found https://antibot.blog/twitter/ where someone investigates this mystic "x-client-transaction-id" header. This is also consistent with @jwom's finding in https://github.com/vladkens/twscrape/issues/175#issuecomment-2199980497. FWIW this header is very likely to be related to account bans. There are also some cloned repos e.g. https://github.com/yeyuchen198/twitter-tid-generator. Highly appreciated if someone can create a python version.
收到
Guys I found the solution
Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
@frameartist Thanks you very much. Based on your answer I modified the login function this way and it worked for me
async` def login(acc: Account, cfg: LoginConfig | None = None) -> Account:
log_id = f"{acc.username} - {acc.email}"
if acc.active:
logger.info(f"account already active {log_id}")
return acc
cfg, imap = cfg or LoginConfig(), None
if cfg.email_first and not cfg.manual:
imap = await imap_login(acc.email, acc.email_password)
async with acc.make_client() as client:
guest_token = await get_guest_token(client)
client.headers["x-guest-token"] = guest_token
rep = await login_initiate(client)
ctx = TaskCtx(client, acc, cfg, None, imap)
while True:
rep = await next_login_task(ctx, rep)
if not rep:
break
# assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)"
client.headers["x-csrf-token"] = "your ct0 string"
client.headers["x-twitter-auth-type"] = "OAuth2Session"
acc.active = True
acc.headers = {k: v for k, v in client.headers.items()}
acc.cookies = {k: v for k, v in client.cookies.items()}
return acc
I have a dozen of accounts and I took one ct0 string from one random logged account using F12 too. It worked for all accounts.
@caterpillar1219 someone on twitter have read this article and changed hash salt from "bird" to "obfiowerehiring" (obfio is article author username on github), the script doesn't work anymore. they changed last byte from 1 to 3, some of the inputs like targetTime, and something else cause i can't manage to fix it
So @frameartist is hard-coding x-client-transaction-id and @bachelow is hard-coding x-csrf-token. Are both of these still working - same code over multiple accounts, still alive after a few days?
So @frameartist is hard-coding x-client-transaction-id and @bachelow is hard-coding x-csrf-token. Are both of these still working - same code over multiple accounts, still alive after a few days?
For me yes, but it become unmanageable with more than 4/5 accounts.
Why unmanageable? I read that you could use the same x-csrf-token on multiple accounts. Did I read that wrong? On Aug 23, 2024, at 5:14 AM, bachelow @.***> wrote:
So @frameartist is hard-coding x-client-transaction-id and @bachelow is hard-coding x-csrf-token. Are both of these still working - same code over multiple accounts, still alive after a few days?
For me yes, but it become unmanageable with more than 4/5 accounts.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>
Guys I found the solution
Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
Your provided solution works great, but I am receiving another issue now Session expired or banned 403 - -1/-1 - SAliukum31074 - OK. The error is in the file queue_client. Has anyone solved this issue or come accross it?
Your provided solution works great, but I am receiving another issue now
Session expired or banned 403 - -1/-1 - SAliukum31074 - OK. The error is in the filequeue_client. Has anyone solved this issue or come accross it?
Yeah that's why I said earlier it was tedious with more than 4/5 accounts. To answer your remark and the one of @takabinance I had to relog using twscrape relogin account several time at the start of my scraping (usually 2 or 3 times) and it ends up working.
Ok, I found the solution, but I'm not sure about the quality.
Anyway: yes, header x-client-transaction-id is required. And this header should generate every request.
Good news: function for generation incomes only 2 args: URI and Method. The function returns base64 string without ends '=' letters.
Bad news: the internal part of the function is very strange and are applied many tricks to avoid deobfuscation. This is possible BUT(!)
The easiest way is using node.js (in CLI mode) and just requesting a URI and method before every request by the client and adding the header. If you want, I can write the simplest node CLI to generate the header.
收到
Guys I found the solution
Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
It's working for me as well. maybe a PR?
Guys I found the solution Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything. Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
It's working for me as well. maybe a PR?
The problem is we need to hardcode the id, which apparently won't last forever. So I'd prefer filing a PR once we reverse engineer the whole mechanism.
Guys I found the solution
Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything.
Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
I tried this method, this base64 string was grab from netword record in chrome(same account), but it still didn't work. And I found "x-client-transaction-id" is diffrent between network records, is the extra verification already enabled on this id?
Ok, I found the solution, but I'm not sure about the quality. Anyway: yes, header
x-client-transaction-idis required. And this header should generate every request. Good news: function for generation incomes only 2 args: URI and Method. The function returns base64 string without ends '=' letters. Bad news: the internal part of the function is very strange and are applied many tricks to avoid deobfuscation. This is possible BUT(!) The easiest way is using node.js (in CLI mode) and just requesting a URI and method before every request by the client and adding the header. If you want, I can write the simplest node CLI to generate the header.
Hi! Any chance to share your solution ?
Guys I found the solution Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything. Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
I tried this method, this base64 string was grab from netword record in chrome(same account), but it still didn't work. And I found "x-client-transaction-id" is diffrent between network records, is the extra verification already enabled on this id?
I meet the problem same with you,the header ‘x-client-transaction-id:’ is different between every request.Did you solve that?I tried to changed account but still.
Your provided solution works great, but I am receiving another issue now
Session expired or banned 403 - -1/-1 - SAliukum31074 - OK. The error is in the filequeue_client. Has anyone solved this issue or come accross it?Yeah that's why I said earlier it was tedious with more than 4/5 accounts. To answer your remark and the one of @takabinance I had to relog using
twscrape relogin accountseveral time at the start of my scraping (usually 2 or 3 times) and it ends up working.
This worked for me the first time, then I removed the account, re-entered it and now will have done twscrape relogin account at least 50 times but it doesn't work.
Has anyone found any other solutions?
maybe the porject https://github.com/iSarabjitDhiman/XClientTransaction is helpful, I successfully logged in with this.
def auto_gen_x_transaction_id() -> str:
headers = {"Authority": "x.com",
"Accept-Language": "en-US,en;q=0.9",
"Cache-Control": "no-cache",
"Referer": "https://x.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
"X-Twitter-Active-User": "yes",
"X-Twitter-Client-Language": "en"}
session = requests.Session()
session.headers = headers
response = handle_x_migration(session)
ct = ClientTransaction(response)
return ct.generate_transaction_id(method="POST", path="/1.1/onboarding/task.json")
then just set the client.headers["x-client-transaction-id"], got it~
收到
maybe the porject https://github.com/iSarabjitDhiman/XClientTransaction is helpful, I successfully logged in with this.
def auto_gen_x_transaction_id() -> str: headers = {"Authority": "x.com", "Accept-Language": "en-US,en;q=0.9", "Cache-Control": "no-cache", "Referer": "https://x.com", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36", "X-Twitter-Active-User": "yes", "X-Twitter-Client-Language": "en"}
session = requests.Session() session.headers = headers response = handle_x_migration(session) ct = ClientTransaction(response) return ct.generate_transaction_id(method="POST", path="/1.1/onboarding/task.json")then just set the client.headers["x-client-transaction-id"], got it~
I just sent a PR to that repo to include asynchronous functionalities, so it will be easier to integrate into twscrape if it's what we need here
maybe the porject https://github.com/iSarabjitDhiman/XClientTransaction is helpful, I successfully logged in with this. def auto_gen_x_transaction_id() -> str: headers = {"Authority": "x.com", "Accept-Language": "en-US,en;q=0.9", "Cache-Control": "no-cache", "Referer": "https://x.com", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36", "X-Twitter-Active-User": "yes", "X-Twitter-Client-Language": "en"}
session = requests.Session() session.headers = headers response = handle_x_migration(session) ct = ClientTransaction(response) return ct.generate_transaction_id(method="POST", path="/1.1/onboarding/task.json")then just set the client.headers["x-client-transaction-id"], got it~
I just sent a PR to that repo to include asynchronous functionalities, so it will be easier to integrate into twscrape if it's what we need here
Hello bro, Please do you have a fix for tall these bugs, especially in auto generating the transaction ids, If possible could you provide me your twitter handle, so I can reach out to you there
i'm facing this issue the most: "Session expired or banned 403 - -1/-1 - SAliukum31074 - OK. The error is in the file queue_client"
maybe the porject https://github.com/iSarabjitDhiman/XClientTransaction is helpful, I successfully logged in with this.
def auto_gen_x_transaction_id() -> str: headers = {"Authority": "x.com", "Accept-Language": "en-US,en;q=0.9", "Cache-Control": "no-cache", "Referer": "https://x.com", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36", "X-Twitter-Active-User": "yes", "X-Twitter-Client-Language": "en"}
session = requests.Session() session.headers = headers response = handle_x_migration(session) ct = ClientTransaction(response) return ct.generate_transaction_id(method="POST", path="/1.1/onboarding/task.json")then just set the client.headers["x-client-transaction-id"], got it~
Hello bro, Is there a way I can reach out to you directly concerning this.. if you're not comfortable with that, can you share your twscrape.queue_client code and your twscrape.login files
Ok, I found the solution, but I'm not sure about the quality. Anyway: yes, header
x-client-transaction-idis required. And this header should generate every request. Good news: function for generation incomes only 2 args: URI and Method. The function returns base64 string without ends '=' letters. Bad news: the internal part of the function is very strange and are applied many tricks to avoid deobfuscation. This is possible BUT(!) The easiest way is using node.js (in CLI mode) and just requesting a URI and method before every request by the client and adding the header. If you want, I can write the simplest node CLI to generate the header.
hello bro, please can you help doing this
maybe the porject https://github.com/iSarabjitDhiman/XClientTransaction is helpful, I successfully logged in with this.
def auto_gen_x_transaction_id() -> str: headers = {"Authority": "x.com", "Accept-Language": "en-US,en;q=0.9", "Cache-Control": "no-cache", "Referer": "https://x.com", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36", "X-Twitter-Active-User": "yes", "X-Twitter-Client-Language": "en"}
session = requests.Session() session.headers = headers response = handle_x_migration(session) ct = ClientTransaction(response) return ct.generate_transaction_id(method="POST", path="/1.1/onboarding/task.json")then just set the client.headers["x-client-transaction-id"], got it~
Please can you share your full code snippet
Guys I found the solution Go to
<your venv or python installation>/site-packages/twscrape/login.pyaround line 264 in the functionasync def login(acc: Account, cfg: LoginConfig | None = None) -> Account:afterclient.headers["x-guest-token"] = guest_token, add a new lineclient.headers["x-client-transaction-id"] = <your client transaction id>The complete function looks like this:async def login(acc: Account, cfg: LoginConfig | None = None) -> Account: log_id = f"{acc.username} - {acc.email}" if acc.active: logger.info(f"account already active {log_id}") return acc cfg, imap = cfg or LoginConfig(), None if cfg.email_first and not cfg.manual: imap = await imap_login(acc.email, acc.email_password) async with acc.make_client() as client: guest_token = await get_guest_token(client) client.headers["x-guest-token"] = guest_token client.headers["x-client-transaction-id"] = "<a base64 string>" rep = await login_initiate(client) ctx = TaskCtx(client, acc, cfg, None, imap) print("-------------------") print(rep.content) print() while True: rep = await next_login_task(ctx, rep) print(rep.content if rep else "No response") print() if not rep: break assert "ct0" in client.cookies, "ct0 not in cookies (most likely ip ban)" client.headers["x-csrf-token"] = client.cookies["ct0"] client.headers["x-twitter-auth-type"] = "OAuth2Session" acc.active = True acc.headers = {k: v for k, v in client.headers.items()} acc.cookies = {k: v for k, v in client.cookies.items()} return accTo obtain a client transaction id, use chrome to login any twitter account then use the F12 developer tools to randomly grab one from the network records. It seems like once you have a valid one you'll be able to login all accounts, so it's quite convenient once you setup everything. Read this stackoverflow for more about how this x-client-transaction-id is generated. I don't have time to reverse engineer this but I hope someone could invent a way to generate these ids automatically in Python
I tried this method, this base64 string was grab from netword record in chrome(same account), but it still didn't work. And I found "x-client-transaction-id" is diffrent between network records, is the extra verification already enabled on this id?
Hello, Have you found a way around this
Your provided solution works great, but I am receiving another issue now
Session expired or banned 403 - -1/-1 - SAliukum31074 - OK. The error is in the filequeue_client. Has anyone solved this issue or come accross it?Yeah that's why I said earlier it was tedious with more than 4/5 accounts. To answer your remark and the one of @takabinance I had to relog using
twscrape relogin accountseveral time at the start of my scraping (usually 2 or 3 times) and it ends up working.This worked for me the first time, then I removed the account, re-entered it and now will have done
twscrape relogin accountat least 50 times but it doesn't work. Has anyone found any other solutions?
please have you found a way around it now