Realtime V3 (macOS, 0.146.0-alpha.3.1): default sideband dials wss://chatgpt.com/backend-api/codex/<call_id> and is blocked by Cloudflare (cf-mitigated: challenge) → 403
Related to #35094, but a different sideband address and a different failure mechanism, so filing separately and cross-linking. #35094 reports the default V3 sideband as wss://api.openai.com/v1/live/<call_id> returning 404 call_id_not_found; on this build the client dials the ChatGPT backend by default and gets 403. #35094 mentions the 403 variant only as something reached by forcing the sideband path — here it is the default, unforced behaviour.
Also distinct from #18456: that one is a User-Agent–dependent Cloudflare block on reqwest clients. This one is User-Agent–independent (control table below).
What version of the Codex App are you using (From "About Codex" dialog)?
App 26.721.41059, bundled runtime codex-cli 0.146.0-alpha.3.1 (ChatGPT.app/Contents/Resources/codex). Homebrew codex-cli 0.145.0 is also installed but is not the binary driving Voice.
What subscription do you have?
Paid ChatGPT subscription (Plus).
What platform is your computer?
macOS 25.5.0, arm64 (Apple Silicon). Cloudflare edge POP SIN.
What issue are you seeing?
Voice chat fails with:
Voice chat error: stream disconnected before completion:
failed to connect realtime websocket: HTTP error: 403 Forbidden
The WebRTC leg succeeds and the sideband WebSocket leg is refused, so audio comes up for roughly a second and then Voice tears itself down when the sideband retry loop is exhausted ~6s later.
Observed sequence, with no experimental_realtime_* overrides set and nothing forced:
POST https://chatgpt.com/backend-api/codex/realtime/calls?intent=quicksilver&architecture=avas
-> 201 Created
-> Location: /v1/realtime/calls/rtc_u0_<redacted>
-> x-codex-plan-type: plus
-> x-codex-active-limit: premium
-> x-codex-primary-used-percent: 2
INFO codex_api::endpoint::realtime_websocket::methods
connecting realtime websocket: wss://chatgpt.com/backend-api/codex/rtc_u0_<redacted>
WARN realtime sideband websocket connect failed; retrying:
stream error: failed to connect realtime websocket: HTTP error: 403 Forbidden
attempt=1 delay_ms=218
attempt=2 delay_ms=387
attempt=3 delay_ms=741
attempt=4 delay_ms=1528
WARN codex_core::realtime_conversation
failed to connect realtime sideband: stream disconnected before completion:
failed to connect realtime websocket: HTTP error: 403 Forbidden
INFO received realtime conversation event event=Error(...)
TRACE app-server event: thread/realtime/error
TRACE app-server event: thread/realtime/closed
Two things to note in that trace:
- The call-create response returns
Location: /v1/realtime/calls/rtc_u0_..., but the sideband URL the client then dials is<base_url>/<call_id>— the/v1/realtime/calls/prefix is dropped. - The
403is not an OpenAI application response. It is a Cloudflare bot-management challenge; the request never reaches the application (evidence below).
What steps can reproduce the bug?
- Sign in with ChatGPT auth (Plus) on macOS arm64.
- Codex Desktop
26.721.41059with bundled runtime0.146.0-alpha.3.1,realtime_conversationenabled. - Start Voice.
- Call creation returns
201; the sideband WebSocket connect towss://chatgpt.com/backend-api/codex/<call_id>returns403and retries 5 times. - Voice closes with the error above.
What is the expected behavior?
The sideband WebSocket joins the freshly created WebRTC call and Voice stays connected.
Additional information
The 403 is a Cloudflare challenge, not an application response
Same access token, same chatgpt-account-id, same machine, same TLS client, run within minutes of a live failure:
| path under https://chatgpt.com/backend-api/codex/ | method | result |
|---|---|---|
| models?client_version=0.145.0 | GET | 200 application/json |
| realtime/calls | POST {} | 400 application/json — reaches the app |
| realtime/calls | GET | 405 application/json — reaches the app |
| rtc_u0_<test> — what the client dials | GET and WS-upgrade | 403 text/html, cf-mitigated: challenge |
| realtime/calls/rtc_u0_<test> | WS-upgrade | 403 cf-mitigated: challenge |
| v1/realtime/calls/rtc_u0_<test> | WS-upgrade | 403 cf-mitigated: challenge |
| realtime/rtc_u0_<test> | WS-upgrade | 403 cf-mitigated: challenge |
| realtime/calls/rtc_u0_<test>/sideband | WS-upgrade | 403 cf-mitigated: challenge |
Every 403 carries server: cloudflare, cf-mitigated: challenge, content-type: text/html, accept-ch: Sec-CH-UA-*, and a ~10KB interstitial HTML body.
Control 1 — not upgrade-dependent. A plain GET with no Upgrade / Connection / Sec-WebSocket-* headers is challenged identically. The mitigation keys on the path, not on the WebSocket handshake.
Control 2 — not User-Agent-dependent, which distinguishes this from #18456:
| User-Agent | models | rtc_u0_<test> |
|---|---|---|
| codex_cli_rs/0.146.0 | 200 | 403 cf-mitigated: challenge |
| Chrome 150 macOS browser UA | 200 | 403 cf-mitigated: challenge |
| (no User-Agent header) | 200 | 403 cf-mitigated: challenge |
So requests carrying the call id never reach the application. They are challenged at the edge, consistent with that path not being covered by the API route exemptions that models and realtime/calls are covered by.
Client-side network ruled out
- No proxy —
scutil --proxyhas noHTTPProxy/HTTPSProxykeys, and no*_proxyenvironment variables are set - No MITM tooling running (no Proxyman / Charles / mitmproxy)
- No VPN exit node in use; default route is the physical LAN interface and egress is the real ISP address
codex_ca_certificate_configured=false ssl_cert_file_configured=false, "using system root certificates" — no certificate interception- A network-level block would also break
modelsandrealtime/calls; both succeed
Not entitlement or quota
The call-create response is 201 with x-codex-plan-type: plus, x-codex-active-limit: premium, x-codex-primary-used-percent: 2. A genuine cap on this account on a different day produced a clearly distinct error (failed to start realtime conversation: You've hit your usage limit. Upgrade to Pro), so the two are easy to tell apart in logs.
No client-side override recovers it
experimental_realtime_ws_base_url and experimental_realtime_webrtc_call_base_url exist in the 0.146 binary, but all five candidate ChatGPT-backend path shapes in the table above are challenged, so there is no config.toml value that restores Voice on this build.
Possible relevance to #35094
If the ChatGPT-backend sideband path is edge-challenged rather than served, then api.openai.com/v1/live/<call_id> is the only sideband address that can currently reach a transceiver — and #35094 reports that one returning call_id_not_found. Both sideband addresses would then be unreachable for ChatGPT-auth sessions by two different mechanisms, which would explain why neither forcing direction produces a working call.
Log history for this account
realtime_websocket::methods connect attempts appear only from the failing session onward. Earlier Voice sessions on the same machine and account started successfully without any sideband connect being attempted, which suggests the sideband leg became active for this session/build rather than having always been on this path.
No access tokens, account ids, user ids, installation ids, real call ids, public IP addresses, or cookies are included above. Call ids in log excerpts are redacted and all probe ids are synthetic.
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I can reproduce this on another Apple Silicon Mac with the exact same Desktop/runtime combination:
26.721.41059codex-cli 0.146.0-alpha.3.126.5.2GRUThe Desktop UI repeatedly closes the realtime voice overlay with:
Local diagnostics ruled out the microphone and ordinary connectivity:
/etc/hostsentries, custom CA configuration, or network system extensions.Direct unauthenticated path controls from the same machine/network produced:
GET /backend-api/codex/realtime/calls→405 application/jsonwithAllow: POST, so the call-creation route reaches the application.GET /backend-api/codex/rtc_test_diagnostic→403 text/html,cf-mitigated: challenge, served by Cloudflare at POPGRU.GET https://api.openai.com/v1/live/rtc_test_diagnostic→ ordinary404, not a Cloudflare challenge.This independently reproduces the path-specific Cloudflare mitigation described in this issue from a different edge POP. Audio transcription works because it uses a separate request flow; only continuous Codex Realtime voice fails.
No access tokens, account IDs, call IDs, public IP addresses, cookies, or attestation values are included here.
Additional affected user with a ChatGPT Pro account and two independent reproductions.
Desktop reproduction
realtime_conversationfeature flag is enabledthread/realtime/startconsistently fails with:stream disconnected before completion: realtime call response missing LocationRouteAll: false, no exit node). A controlled test with Tailscale fully stopped confirmed the Mac still reached OpenAI normally.Patched-runtime reproduction
codex-cli 0.147.0-alpha.1runtime.438c9e98db71273e4f0b63dc4a86c2db58c44706is an ancestor of that release.realtime call response missing Locationerror.iOS reproduction
Voice couldn’t connect — Please check your connection and try again.thread/realtime/startfor the mobile attempt, indicating the iOS Voice failure occurred before handoff to the host.This looks account/realtime-backend specific rather than a microphone, local installation, home-network, VPN, or Tailscale problem. Please investigate the affected account’s Voice entitlement and realtime call-creation/routing response. The feature is advertised for Pro and Remote on iOS, but it is unusable on both supported surfaces.
Additional reproduction on a newer macOS app/runtime
I am also affected by the Voice startup failure described in this thread. The installed versions are newer than those in the original report:
26.727.40816(build6067)codex-cli 0.146.0-alpha.9.2codex-cli 0.146.026.5.2(build25F84)uname -mprs):Darwin 25.5.0 arm64 armMac16,1When starting Codex Voice, the app shows:
Expected: the Voice session starts successfully.
Actual: Voice fails during startup before the conversation begins.
This confirms that the exact
realtime call response missing Locationsymptom persists on app26.727.40816with bundled runtime0.146.0-alpha.9.2. I previously mentioned the symptom in #35474, but that issue primarily tracks a different failure mode (Connection reset by peerafter 15–20 seconds), so this thread appears to be the closer match.No account IDs, tokens, call IDs, or other secrets are included.
Still reproducible — screen recording (Aug 8, 2026)
This is still failing on the same Mac/account from my Jul 27 reproduction, 13 days after this issue was opened.
The attached 15-second screen recording shows the current behavior:
Regular ChatGPT microphone transcription continues to work on this Mac; only continuous Codex Voice is blocked.
This issue now has several independent confirmations, including reproductions on newer app/runtime versions, but there has not yet been a maintainer acknowledgment. Could an OpenAI maintainer please confirm whether this realtime call-creation/routing failure is being tracked and whether any additional diagnostics would help? The feature remains completely unusable for affected users.
Screen recording:
https://github.com/user-attachments/assets/4aacbae1-4333-4ca5-9f33-bf1185f76b05
Additional Windows reproduction — app 26.803.5235.0
I can reproduce the same exact Realtime WebSocket failure in Codex Desktop on Windows:
OpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g0The local sequence shows
thread/realtime/startsucceeding and the realtime session starting, followed by:Local controls:
127.0.0.1:3067This rules out the microphone and makes the Windows realtime WebSocket route/proxy handling the likely failure point. I cannot confirm from the available local log line alone whether this specific 403 is the same Cloudflare challenge described in the original report, but the user-visible and app-server error is identical.
In-app diagnostic feedback was submitted with ID:
019fe94c-90a5-7300-821e-0b01a1c9a0c3Please correlate the server-side session/edge response with that feedback ID and check whether the Windows realtime sideband WebSocket honors the system proxy or is taking a different route from the rest of the app.
No raw logs, tokens, account IDs, public IPs, or browsing data are included here.
happening for me too. happening for weeks and nothing has changed. contacted support and they weren't any help.
<img width="867" height="301" alt="Image" src="https://github.com/user-attachments/assets/1dc452c4-cdf6-46c9-abc1-b75d52ef06b4" />