twitter x api 401 unauthorized bearer token error
This skill fixes Twitter/X API 401 unauthorized bearer token errors. Use it when API calls fail auth or when rotating tokens. It is not for 403 tier errors; the fix is the exact Bearer header, a clean token value, regeneration when exposed, and confirming app permissions.
Twitter X API 401 unauthorized bearer token error
TL;DR
A 401 on the X API means the bearer token is missing, expired, or revoked, or the app's permissions do not cover the endpoint. Regenerate the token in the developer portal, confirm the app has the right access level, and send it as a your bearer credential header exactly. Never commit the token to a repo; a leaked token gets revoked and the 401s come back.
The error
HTTP 401 Unauthorized
{"errors": [{"message": "Unauthorized", "code": 32}]}When this helps
- X API calls return 401 unauthorized
- a bearer token stops working
- setting up X API access for a new agent
- rotating a compromised token
When it doesn't
- the error is 403; that is tier gating or suspension, not the token
- the error is 429; that is rate limit
- the app itself was suspended; regenerate nothing until the appeal resolves
Works with
X API v2 as of 2026 with OAuth 2.0 bearer tokens.
Steps
1. Send the bearer token in the exact header form
curl -s "https://api.twitter.com/2/tweets/search/recent?query=test" -H "your auth header -o probe.json -w "HTTP %{http_code}\n"
head -c 200 probe.json; echoExpected: HTTP 200 with the app user. The header is Authorization colon Bearer space token; any deviation 401s.
2. Check the token value for whitespace damage
import os
t = os.environ.get("X_BEARER", "")
print("length:", len(t))
print("clean:", t.strip() == t and " " not in t)Expected: A clean token string. Pasted tokens often carry trailing newlines that break auth silently.
3. Regenerate the token if it was exposed or is stale
import os
print("regenerate in the developer portal under the app's keys section")
print("update the secret store, then re-run the step-1 call")
print("old token stays valid until you revoke it; revoke after verifying the new one")Expected: A rotation procedure. Tokens in git history or logs must be treated as compromised.
4. Confirm the app permission level covers the endpoint
import requests, os
r = requests.get("https://api.twitter.com/2/tweets/search/recent", headers={"Authorization": "Bearer " + os.environ["X_BEARER"]}, params={"query": "x"}, timeout=20)
print(r.status_code, "(403 here means tier, not token)")Expected: A 200, or a 403 that proves the token works and the endpoint needs a higher tier. Token fixed versus tier gated are different problems.
Other ways people phrase this
twitter api 401 bearer token
Token hygiene: exact header, clean value, fresh generation.
x api unauthorized code 32
The classic bad-token code. Regenerate and retest.
twitter bearer token expired
Bearer tokens do not expire by time, but revocation and app changes invalidate them.
Why it happens
The X API authenticates every call with a bearer token tied to the app's keys. The 401 means the token presented is not valid: wrong value, whitespace damage, revoked, or from a deleted app. The API cannot distinguish these, so verify the value, the header form, and the app state in order.
Edge cases
- OAuth 1.0a user tokens and OAuth 2.0 bearer tokens are different; use the right one per endpoint.
- A token that works on one endpoint but 401s elsewhere points at app permissions, not the token.
- Rate limits can masquerade as auth flakiness under retry storms; check the code, not just the symptom.
- Store tokens in a secret manager; environment files get committed by accident.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst24fsE803v3iELKGWecU4A
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.