Get X API credentials for automated posting
Produces an OAuth 2.0 user-context access token. Follow this in order; step 2 has a 30-second deadline.
That one authenticates the application, not the account. It cannot post, and it fails in a way that looks like it worked: the account connects, reports healthy, and only errors later. The deliverable here is a user-context token.
1 · Create the app
-
Open
developer.x.com/en/portal/dashboardand sign in as the account the bot will post from. - Sign up for the Free tier if prompted. It allows roughly 1,500 posts a month, which is enough. Do not buy a paid tier.
- Create a Project, then an App inside it.
- App → Settings → User authentication settings → Set up, and enter:
| App permissions | Read and write |
| Type of App | Web App, Automated App or Bot |
| Callback URI | https://localhost:3000/callback |
| Website URL | any URL you own |
Save, then open Keys and tokens and copy the OAuth 2.0 Client ID and Client Secret.
Record it now. Regenerating it invalidates the old one.
2 · Authorize, and grab the code
Open it, confirm the consent screen names the right account, and click Authorize app.
It redirects to https://localhost:3000/callback?... and nothing is listening
there. What matters is the URL in the address bar — copy all of it, and take the value of
code= (it ends at the first &, if there is one).
Have step 3 ready before you click Authorize. If it expires, just redo step 2.
3 · Exchange the code for a token
Run this in a terminal. It cannot be done from a web page — X’s token endpoint sends no CORS headers, so a browser request is blocked before it is sent.
Fill the three fields above.
A successful response is JSON containing access_token and
refresh_token. If you get invalid_grant or
invalid_request, the code expired or was already used. Redo step 2.
4 · Verify before handing it over
Confirm the token really is user-context, rather than discovering it later:
curl -H "Authorization: Bearer ACCESS_TOKEN" https://api.x.com/2/users/me
JSON with the account’s id and username.
An error mentioning “Application-Only” or “OAuth 2.0 User Context” means you captured the app-only Bearer Token. Go back to step 2.
What to hand back
CLIENT_IDCLIENT_SECRETaccess_tokenrefresh_token
Anyone holding the access token can post as the account. Send them through whatever
private channel was agreed, not a chat log, an issue, or a file that outlives the task.
Revoke any time at x.com/settings/connected_apps.
What this token can and cannot do
| Post | Yes. Free tier, roughly 1,500 a month |
| Read timelines | No. Paid endpoint; the platform reads via Nitter instead, which needs no credential |
| Search | No. Paid, and no free substitute currently works |
| DMs | No. Requires a browser session, captured separately |