Summary
Since the x.com homepage redesign, twitter search "query" -n 10 fails with HTTP 404 on every request. twitter feed, tweet, user-posts still work.
Environment
- twitter-cli v0.8.5 (latest on PyPI, 2026-03-17)
- macOS
Reproduce
$ twitter search "agent" -n 3
WARNING twitter_cli.client: Failed to init ClientTransaction: 'NoneType' object has no attribute 'group'
ok: false
error:
code: not_found
message: 'Twitter API error (HTTP 404): Twitter API error 404: '
Root cause analysis
-
_ensure_client_transaction() (client.py) fetches https://x.com and parses the homepage with get_ondemand_file_url() in x_client_transaction/utils.py:
on_demand_file_index = ON_DEMAND_FILE_REGEX.search(str(response)).group(1) # line 59
The new x.com homepage HTML no longer matches ON_DEMAND_FILE_REGEX, so .group(1) raises 'NoneType' object has no attribute 'group'. ClientTransaction init is wrapped in try/except (client.py:1092-1093), so it only logs a warning.
-
Because ClientTransaction init fails, the dynamic queryId scan (from JS bundles) is also effectively unavailable, so the client falls back to the hardcoded SearchTimeline queryId in graphql.py (MJpyQGqgklrVl_0X9gNy3A) which is stale — Twitter returns 404 for unknown queryIds.
-
Other endpoints (HomeTimeline, UserTweets, etc.) still work because their queryIds haven't been rotated yet.
Suggested fix
- Update
get_ondemand_file_url() regex parsing for the new x.com homepage structure (or make it non-fatal so bundle scanning / queryId refresh still runs)
- Refresh the
SearchTimeline queryId from current x.com JS bundles
Happy to provide more debugging info if needed.
Summary
Since the x.com homepage redesign,
twitter search "query" -n 10fails with HTTP 404 on every request.twitter feed,tweet,user-postsstill work.Environment
Reproduce
Root cause analysis
_ensure_client_transaction()(client.py) fetches https://x.com and parses the homepage withget_ondemand_file_url()inx_client_transaction/utils.py:The new x.com homepage HTML no longer matches
ON_DEMAND_FILE_REGEX, so.group(1)raises'NoneType' object has no attribute 'group'. ClientTransaction init is wrapped in try/except (client.py:1092-1093), so it only logs a warning.Because ClientTransaction init fails, the dynamic queryId scan (from JS bundles) is also effectively unavailable, so the client falls back to the hardcoded
SearchTimelinequeryId in graphql.py (MJpyQGqgklrVl_0X9gNy3A) which is stale — Twitter returns 404 for unknown queryIds.Other endpoints (HomeTimeline, UserTweets, etc.) still work because their queryIds haven't been rotated yet.
Suggested fix
get_ondemand_file_url()regex parsing for the new x.com homepage structure (or make it non-fatal so bundle scanning / queryId refresh still runs)SearchTimelinequeryId from current x.com JS bundlesHappy to provide more debugging info if needed.