Codex error 403: causes and how to keep working
A 403 in Codex comes in three kinds: a region refusal, an account problem and gateway key restrictions. How to tell them apart by the error text and what to fix.
5 min · · errors · IDE
When a 403 error shows up in Codex, the worst part is that it has no single cause. The same response code comes both from OpenAI, when it refuses by country or account, and from a gateway, when a key is not allowed to use a model. They are fixed differently, so the first action is not "reconfigure everything" but to find out who exactly refused. Below: the diagnostic order, a table of causes and concrete Codex config fixes.
Codex error 403: where it comes from
HTTP 403 means "the request is understood but will not be carried out". In a Codex-plus-API setup, different links in the chain can refuse:
| Who refused | What it looks like | What to do |
|---|---|---|
| OpenAI directly: region | the error text mentions a country, region or territory where the service is not supported | this is not fixed by Codex settings; point Codex at another provider (see below) |
| OpenAI directly: account | a refusal at sign-in, a request for confirmation such as a phone number | these are the rules of the OpenAI account itself; Codex cannot affect them |
Zukko gateway: model_not_allowed_for_key | JSON with this code; the model is not in the key's allowed list | add the model to the key or change the model in Codex |
Zukko gateway: email_unverified | JSON with this code; the email in the dashboard is not verified | verify the email in the dashboard |
It is easy to tell them apart by the text: Zukko errors end with the line "Поддержка — https://t.me/zukkopro?direct, напишите, пожалуйста" (Support: write to us on Telegram), and the code is in the error.code field. If there is no such line, the answer came from another link.
Step 1. Find out where Codex actually goes
If Codex is set up by default, it calls OpenAI, and then a 403 by region is entirely expected: regional restrictions are set by OpenAI, not by you or us. We do not suggest schemes for bypassing, faking a region or using other people's accounts: they break the service rules and can lead to a ban. The lawful route from Russia is a different provider in the config: access through the gateway, payment by SBP, a MasterCard card or crypto.
Open ~/.codex/config.toml (on Windows %USERPROFILE%\.codex\config.toml) and compare it with the standard one:
model = "gpt-6.1-sol"
model_provider = "zukko"
model_reasoning_effort = "high"
[model_providers.zukko]
name = "zukko"
base_url = "https://api.zukko.pro/v1"
wire_api = "responses"
requires_openai_auth = trueCheck three things. First: the line model_provider = "zukko" is in place and the name matches the [model_providers.zukko] header. Without it Codex goes to OpenAI. Second: base_url ends with /v1. Third: ~/.codex/auth.json with the key sits next to it:
{ "OPENAI_API_KEY": "fetch_..." }If you used to sign in to Codex through an account, this file may hold data from the earlier sign-in. Make a backup of the file and write the key in. According to the Zukko instructions a separate OpenAI account sign-in is not needed: the key is taken from auth.json. The automatic setup with backups is described in the Codex guide.
Step 2. About the phone number request
"Codex asks for a phone number" is most often tied to registering and verifying an account on the OpenAI side, not to Codex itself. That is an account condition, and there is no need to act around it. If you work through a gateway key, an OpenAI account is not used for requests, and such a step should not appear. If it still appears, Codex most likely did not read your config (step 1) or is run under another user with a different home directory.
Step 3. Test the key with a separate request
To separate a Codex problem from a key problem, send a request bypassing Codex:
curl -i https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer $ZUKKO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-6.1-sol","messages":[{"role":"user","content":"ping"}],"max_tokens":16}'Read the status code and the body:
- 200. The key, model and balance are fine. So the 403 does not come from the gateway: go back to step 1 and check where Codex goes.
- 403
model_not_allowed_for_key. The key has an allowed-model list and yours is not in it. Open the key in the dashboard and add the model to the list, or changemodelinconfig.toml. You can also change the model at launch:codex -m gpt-6.1-sol. - 403
email_unverified. Verify your email in the dashboard. With a Telegram sign-in no verification is required. - 401. The key has a typo or was revoked. 402. The balance is below $0.01. These are other errors, but at first glance they are often confused with 403.
If config.toml names a model that is not in the catalogue, the answer is 404 model_not_found. The current model list is public: GET https://api.zukko.pro/v1/models.
A common trap: a model Codex cannot use
According to the Zukko documentation, Codex goes through the Responses API, so GPT and Claude models fit. GLM models do not work in Codex. If you restricted a key to a GLM model to save money while Codex has GPT, you get exactly a 403. The fix is simple: for the Codex key allow the model you put in model.
It is worth knowing more about restricting keys: how to allow a key only the models it needs and error 403 model_not_allowed_for_key.
How to keep working while you sort it out
- Create a separate key for Codex with a daily limit and the list of models you really use. Then
model_not_allowed_for_keyappears where you expect it. - Keep one verified model in
config.tomland change it throughcodex -mrather than editing the file. - After any config edit run a short task, for example "print the Node version in the project", and make sure an answer arrives.
To check spend, look at "Usage" in the dashboard: a request that reached the model shows up there, while a rejected 403 charges nothing.
FAQ
Why does Codex give a 403 when I have a balance?
Balance affects 402. For 403 the reason is different: region or account when calling OpenAI directly, the key's allowed-model list or an unverified email. Tell them apart by the response text and the error.code field.
Does Codex need a region bypass?
We do not advise or describe such schemes. For work from Russia use another provider in the config: access through the gateway, payment by SBP, a MasterCard card or crypto.
Can I use Codex without a ChatGPT subscription?
Yes, Codex reads its provider from the config, so you can point it at a compatible API and pay for tokens. Step-by-step setup is in the article Codex without a ChatGPT subscription.
The 403 appeared after I changed the model. What should I check?
The key's allowed-model list. The new model must be added to it, otherwise the gateway returns model_not_allowed_for_key.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- JetBrains AI Assistant not working: causes and workaroundsAI Assistant will not activate, stays silent or is off for some files. We go through the causes in the JetBrains docs and connect your own models via a gateway.
- Invalid API key in opencode: why the key is rejected and how to checkThe Invalid API key error in opencode almost always comes down to four causes. We test the key outside opencode and find where the chain breaks.
- Cursor not working: common problems and how to fix themCursor froze, shows Reconnecting or does not answer. We go from simple causes to complex ones and cover problems with your own key and a gateway separately.
- Cursor AI limits: how they work and what to do when you run outA Cursor limit is consumption of an included amount of usage, not a message counter. What eats it and four ways to keep working when it runs out.