Check as one or more of these causes could be at play:
Mismatched Redirect URI
The redirect_uri you send in your /authorize URL must exactly match the redirect URL registered in the Twitter/X Developer Portal — including scheme, domain/IP, port, and trailing slashes.
If you registered http://127.0.0.1/ but your request uses http://127.0.0.1 (no trailing slash), or vice versa, it will fail with 403.
Scopes vs App permissions
Even if your app permissions in the portal say “Read and Write,” if your /authorize request includes scopes not allowed by your app config, it can fail.
Your scopes look correct (tweet.write tweet.read users.read) if your app was approved for tweet posting.
Client ID or secret invalid/mismatched
Double-check that your client_id exactly matches what’s shown for your app in the developer portal.
Make sure you’re using your app’s OAuth2 Client ID, not your API Key.
Incorrect endpoint URL
The correct base domains for X/Twitter API calls are:
API requests:
(Still api.twitter.com as they have not migrated API calls to an api.x.com domain.)
OAuth2 authorization:
https://twitter.com/i/oauth2/authorize
The domain api.x.com does not exist or serve any public API endpoints which is why your browser immediately hit a 403 Forbidden: that hostname either routes nowhere meaningful or returns an error by default.