User Agents — Every UA the Desktop App and Its Clients Send
User Agents — Every UA the Desktop App and Its Clients Send
Part of openai-research. A standalone must present the right User-Agent per surface — servers route/validate by client type (this is also hypothesis for detections). Captured UAs, 2026-08-26:
| Context | UA | Notes |
|---|---|---|
| Main process requests (chat submode flow) | Codex Desktop/26.820.60940 (Mac OS; arm64) | X-OpenAI-Attach-* headers, originator: Codex Desktop; app self-updated 26.818 → 26.820 during session |
| Sentinel fallback (flip win32/x64) | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36 | With full sec-ch-ua set + sec-ch-ua-platform: "macOS"; originator: Codex Browser (NOT Desktop!) |
| Plugin primary runtime download | codex-primary-runtime-installer | GET persistent.oaistatic.com/codex-primary-runtime/26.826.11250/codex-primary-runtime-darwin-arm64-26.826.11250.tar.xz — on-demand plugin runtime (see architecture) |
| Bezetacil hooks | none (they run in-process) | — |
| Legacy probe files | dsh-openai-probe/0.1 (security research) | stale probes only (not a real client identity) |
| Web (site/browser route) | browser-consistent (the user's Safari etc.) | the route that uses cookies + sentinel web PoW |
Details that matter for a standalone:
- Version strings are part of the identity:
Codex Desktop/26.820.60940 (Mac OS; arm64)— theclient_versionin/codex/models?client_version=…tracks the binary build; if the requirement is "binary installed and updated", the harness should mirror the installed app version. - The sentinel fallback swaps in a browser UA +
Codex Browseroriginator (sec-ch-uasays Chrome/151) while the fingerprint continues to carry the real webview chunk (app://-/assets/index-*.js) — a deliberately mixed identity (desktop renderer with browser frames). - The rust side (app-server) does not set a UA of its own in the observed requests (owned
codex_http_clientrequests to/backend-api/codex/*carry the API path + attestation headers; UA default hyper/reqwest, not observed in traces).X-OAI-IS: not observed in the executed flows (A/A1/manual); flow B: unknown (not executed).
TypeScript types (the UA surface)
/** The main-process desktop UA — version is the app build (getVersion). */
export interface DesktopUa {
product: `Codex Desktop/${string}`
platform: 'Mac OS; arm64' | string
toString(): string // 'Codex Desktop/26.820.60940 (Mac OS; arm64)'
}
/** Builder: `Codex Desktop/${app.getVersion()} (Mac OS; arm64)` */
/** The sentinel-fallback browser UA (flip). */
export interface BrowserUa {
product: 'Mozilla/5.0'
platform: '(Macintosh; Intel Mac OS X 10_15_7)' // the observed flip value
engine: 'AppleWebKit/537.36 (KHTML, like Gecko)'
chrome: 'Chrome/151.0.0.0'
safari: 'Safari/537.36'
secChUa: '"Chromium";v="151", "Google Chrome";v="151", "Not=A?Brand";v="24"'
secChUaMobile: '?0'
secChUaPlatform: '"macOS"'
}
export const CDPX_UA_HEADER = 'codex-primary-runtime-installer' // plugin runtime downloader
export const ORIGINATORS = { desktop: 'Codex Desktop', browser: 'Codex Browser', cli: 'codex_cli_rs' } as const
Cross-references
- chatgpt-desktop-architecture — where each UA goes (main vs renderer vs app-server)
- sentinel-fallback-validation — the fallback UA in action
- chat-submode-protocol — the chat submode headers
- flow-a-manual-step-by-step — the validated header set for flow A1