From 30536c2aa06de6b933ba6ef6ed731fcc3facea2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdurrahman=20=C3=96zkan?= Date: Sat, 1 Aug 2026 21:54:20 +0300 Subject: [PATCH] fix: send auth cookies when fetching x.com home for ClientTransaction init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _ensure_client_transaction() fetched https://x.com with a fresh, unauthenticated curl_cffi session (no cookies). Since Aug 2026, the logged-out x.com response no longer contains the ,:"ondemand.s" webpack chunk marker that get_ondemand_file_url() looks for, so ClientTransaction init silently fails (caught by the broad except in _ensure_client_transaction) and the client falls back to a stale hardcoded SearchTimeline queryId, which Twitter now 404s on. Fetching https://x.com/home with the session's own auth_token/ct0 cookies returns the authenticated app shell, which still contains the ondemand.s marker, so ClientTransaction initializes correctly and search works again. Fixes #78. Same underlying issue as #74/#69/#73. Closes the gap left by #71 (which proposed the same cookie fix but was closed unmerged) — this version also switches the request target from /home's parent (x.com) to x.com/home directly, matching where the authenticated bundle actually lives. Verified locally: `twitter search "seedance prompt" -n 3` returns real results post-patch, 404s pre-patch, using two different accounts (one brand-new, one 2+ years old) to rule out account-age throttling as the cause. --- twitter_cli/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/twitter_cli/client.py b/twitter_cli/client.py index 0436c8e..7ac84b3 100644 --- a/twitter_cli/client.py +++ b/twitter_cli/client.py @@ -1103,8 +1103,9 @@ def _ensure_client_transaction(self): # a different TLS fingerprint on the same IP — a detection vector. cffi_session = _get_cffi_session() ct_headers = _gen_ct_headers() + ct_headers["Cookie"] = "auth_token={}; ct0={}".format(self._auth_token, self._ct0) home_page = cffi_session.get( - "https://x.com", headers=ct_headers, timeout=10, + "https://x.com/home", headers=ct_headers, timeout=10, ) home_page_response = bs4.BeautifulSoup(home_page.content, "html.parser") ondemand_url = get_ondemand_file_url(response=home_page_response)