Archonum API Documentation
Archonum is a residential proxy network running on real devices. There are four ways to use it:
- REST API — request connection details for a proxy over HTTPS, then use them with any client.
- Direct gateway — point any HTTP or SOCKS5 client at
stagegw.archonum.comwith your username + token. - JavaScript SDK — drive real-device Chrome over CDP from your own code.
- MCP server — give an AI agent a stealth browser, no code.
Quickstart
- Start a free trial — 1 GB of bandwidth, 7 days.
- Copy your token from the API Key page.
- Make a request through the gateway:
curl -x http://YOUR_USERNAME:YOUR_TOKEN@stagegw.archonum.com:10080 https://ip-api.com/json
The response shows the exit IP, which is a residential device — not our servers.
Interactive reference: Swagger UI · ReDoc · OpenAPI YAML · llms.txt
Authentication
Most surfaces authenticate with your API token — sign in and copy it from the API Key page. The MCP endpoint additionally supports OAuth 2.1, which is what interactive AI clients use.
REST API: pass the token in the Authorization header.
Authorization: Token YOUR_API_TOKEN
Gateway (HTTP / SOCKS5 / CDP): your username is the proxy username, the token is
the proxy password. The gateway answers 407
for any credential problem, including an empty balance.
SDK: reads ARCHONUM_USERNAME
and ARCHONUM_TOKEN from the environment.
MCP: either HTTP Basic with username:token,
or OAuth 2.1. Note that OAuth still requires the
account to hold an API token — the MCP service uses it to open gateway sessions on your behalf.
Regenerating your API key invalidates the previous one everywhere, immediately, including live OAuth sessions.
REST API
Base URL: https://stage.archonum.com/api/v1
GET /api/v1/proxies/
Returns connection details for an available proxy. Requires a non-zero balance
(402 otherwise); the bandwidth itself is metered as you use the proxy.
Query params (all optional):
country— ISO 3166-1 alpha-2, case-insensitive (US,us).session— sticky-session label. Non-alphanumeric characters are stripped and it is truncated to 32 characters, somy_idbecomesmyid.ttl— how long the sticky session holds its exit, in minutes. Clamped to 1–720; defaults to 10. Ignored withoutsession.
curl -H "Authorization: Token YOUR_TOKEN" \ "https://stage.archonum.com/api/v1/proxies/?country=US&session=mysession&ttl=60"
Response: host, http_port, socks_port,
cdp_port, username (with the suffixes applied),
password, proxy_type, country,
session, ttl_minutes, connection_string,
cdp_url, curl_http, curl_socks5.
GET /api/v1/browsers/
Returns a CDP WebSocket URL for a real-device Chrome session, with credentials embedded as query parameters — attach Playwright, Puppeteer, or any CDP driver to it. Costs 5 MB up front, whether or not you then use the session.
Query params: country, session,
ttl — same rules as /proxies/ above.
curl -H "Authorization: Token YOUR_TOKEN" \ "https://stage.archonum.com/api/v1/browsers/?country=US&session=mysession&ttl=60"
Response: endpoint_url (the CDP WebSocket URL),
country, country_name.
GET /api/v1/credits/
What the account can currently spend, in MB.
curl -H "Authorization: Token YOUR_TOKEN" \ "https://stage.archonum.com/api/v1/credits/"
Response: username, credits (spendable MB — this is
the figure every endpoint and the gateway enforce), balance (MB on the account,
ignoring trial expiry), trial_expires_at (null when not on a trial).
Once a trial lapses, credits is 0 while balance keeps
its value — see Billing.
GET /api/v1/health/
Public service probe. No authentication required. Always answers
200; read {"healthy": true|false} from the body
rather than the status code. The gateway exposes its own probe on the CDP port at
/health, which does use 200/503.
curl "https://stage.archonum.com/api/v1/health/"
Direct gateway usage
You don't have to call the REST API for every request. Point any HTTP/SOCKS5 client at the gateway directly.
Options travel in the username as suffixes, which the gateway strips before looking up your token:
{username}[-country_{CC}][-session_{ID}][-ttl_{MINUTES}]
-country_— two ASCII letters, case-insensitive.-session_—[a-zA-Z0-9_]+; underscores are fine here, unlike the RESTsessionparameter, which strips them.-ttl_— digits only. Values at or below 0 fall back to 10 minutes, and anything above 720 is capped at 12 hours rather than rejected.- Order does not matter and suffixes may repeat — the parser strips from the end until nothing matches. The bracket notation above is convention, not a requirement.
CDP takes the same options as query parameters instead of username suffixes.
This is the URL shape /api/v1/proxies/ returns as
cdp_url and /api/v1/browsers/ as
endpoint_url:
ws://stagegw.archonum.com:10900/devtools/browser?username=USER&password=TOKEN[&country=us][&session=ID][&ttl=60]
HTTP proxy
curl -x http://USER:TOKEN@stagegw.archonum.com:10080 https://ip-api.com/json
SOCKS5 proxy
curl --socks5 USER:TOKEN@stagegw.archonum.com:10443 https://ip-api.com/json
Country filtering
Append -country_XX — an ISO 3166-1
alpha-2 code, case-insensitive. If no device is available in that country the request fails
with 404 (REST) or 502 (gateway) rather than
silently falling back to another country.
curl -x http://USER-country_us:TOKEN@stagegw.archonum.com:10080 https://ip-api.com/json
Sticky sessions
Append -session_ID; reusing the same
ID keeps you on the same exit for the session's lifetime. Add
-ttl_MINUTES to control that
lifetime — 10 minutes by default, up to 720 (12 hours).
curl --socks5 USER-country_us-session_abc123-ttl_60:TOKEN@stagegw.archonum.com:10443 https://ip-api.com/json
Two caveats worth knowing. A session pins a device group, not a single IP address — a residential device can change address underneath you, so treat the exit IP as stable-ish, not guaranteed. And the sticky key includes the protocol, so the same session label used over HTTP and over SOCKS5 resolves to two different exits; use one protocol per session.
JavaScript SDK
archonum-sdk-js drives real-device Chrome through the CDP gateway from your own code — stealth automation with Playwright, Puppeteer, or any CDP driver. Three packages:
@archonum/sdk— client: credentialed CDP URLs, health, credits@archonum/engine— session management, stealth reads, human-like interaction@archonum/cli— one-shot page reads from the terminal
npm install @archonum/sdk @archonum/engine
Authenticate via environment: ARCHONUM_USERNAME
and ARCHONUM_TOKEN (your API token).
import { ArchonumClient } from '@archonum/sdk';
const client = ArchonumClient.fromEnv(); // reads ARCHONUM_USERNAME / ARCHONUM_TOKEN
const url = await client.getCDPUrl(); // attach Playwright, Puppeteer, or any CDP driver
One-shot stealth read from the terminal:
npx @archonum/cli https://example.com
Source on GitHub · npm. Prefer zero code? The hosted MCP server exposes the same engine to AI agents.
MCP for AI agents
Archonum ships a hosted MCP server — a real-device stealth browser your AI agent can drive: stealth page reads, interactive sessions with a chosen exit country, clicks, forms, screenshots, and cross-country comparisons. Nothing to install.
https://stage.archonum.com/mcp
Authenticate via OAuth 2.1 (interactive clients like Claude, ChatGPT, Codex — add the URL and sign in) or HTTP Basic with your username and API token (headless setups). Per-client setup instructions live on the MCP page after sign-in; the machine-readable agent guide is at /skill.md.
OAuth 2.1
Compliant clients discover everything they need from the metadata documents and need no manual configuration. The details, for anyone writing a client by hand:
| Item | Value |
|---|---|
| Discovery | /.well-known/oauth-authorization-server (RFC 8414) and /.well-known/oauth-protected-resource (RFC 9728). A 401 from the MCP endpoint points at the latter in its WWW-Authenticate header. |
| Endpoints | /o/authorize/, /o/token/, /o/register/, /o/revoke_token/ |
| Flow | Authorization code. PKCE is mandatory and only S256 is accepted — a client without PKCE cannot connect. |
| Scope | A single scope, mcp. Tokens without it are rejected. |
| Lifetimes | Access token 1 hour, refresh token 30 days and rotating. A client that cannot refresh stops working after an hour. |
| Registration | Dynamic client registration (RFC 7591) at /o/register/, unauthenticated but limited to 30 registrations per hour per caller — exceeding it returns 429. Grant types authorization_code and refresh_token; auth methods none, client_secret_post, client_secret_basic. |
| Redirect URIs | https on any host; http only on localhost, 127.0.0.1, or [::1]. Anything else is refused with invalid_client_metadata. |
| Revoking | Clients can call /o/revoke_token/. To revoke every grant at once, regenerate your API key on the API Key page — the MCP uses it to reach the gateway, so all sessions stop. |
Limits & lifecycle
Sessions are ephemeral server-side resources, not durable state. Agents should treat any of the following as normal and reopen rather than fail:
- 5 open sessions per account. Opening a sixth fails until one is closed.
- 3 concurrent
read/compare_countriescalls, shared across both tools. - Idle sessions are reaped after 10 minutes; a named session then reports "is not open" and must be reopened. Only
defaultopens itself on demand. - An account idle for 30 minutes loses its whole pool, which surfaces as "session pool was reclaimed after being idle; retry to get a fresh one". Retrying works.
- MCP session ids expire after 30 minutes of no requests; the client then gets
404 unknown sessionand must re-initialize. - Requests are capped at 4 MB (
413); page loads time out at 90 seconds;wait_for_contentaccepts at most 60 seconds. - Reopening an existing session name with a different country replaces it — the old page and its state are gone, same as
freshIdentity. - An empty balance returns
402, not401. Do not re-authenticate; top up.
Tools
? marks optional arguments. All country arguments
take ISO 3166-1 alpha-2 codes ("ch", "it", "us");
omitted, the server default applies. Full argument schemas are served to the client by the MCP protocol itself.
Reading pages
| Tool | Arguments | Description |
|---|---|---|
| read | url, country?, waitForText?, minTextLength?=200, screenshot?=false | One-shot stealth fetch: rendered text of a URL, optionally as seen from a country. The web_fetch substitute — no session needed. waitForText makes JS-heavy reads deterministic. Output is capped at 8,000 characters and marked …(truncated); for more, drive a session and use get_text. |
Sessions
| Tool | Arguments | Description |
|---|---|---|
| open_session | name, country?, freshIdentity?=false | Open a named session pinned to an exit country. Sessions are independent; freshIdentity rotates to a new device/exit IP when a bot wall hard-blocks. |
| close_session | name | Disconnect and drop a named session. |
| list_sessions | — | Open sessions with exit country and current URL. |
| page_info | session? | Current URL, title, status, bot-wall flag, viewport/device profile, open-dialog state. |
Navigating & inspecting
| Tool | Arguments | Description |
|---|---|---|
| navigate | url, waitUntil?=load, session? | Load a URL in a session for interaction. Reports a bot-wall blocked flag with challenge classification. |
| back | session? | Go back one history entry (browser Back button) — result page back to the list without re-navigating. |
| wait_for_content | minTextLength?=200, containsText?, timeoutMs?=15000 (max 60000), session? | Poll until real content renders (bot wall clearing, slow JS). stalled=true means the identity is hard-blocked — reopen with freshIdentity. |
| snapshot | session? | Ref-tagged outline of interactive elements ([e12] button "Save"). Pierces open shadow DOM and same-origin iframes. Refs drive click/type. |
| get_text | selector?, selector?, maxChars?=8000 (max 50000), session? | Rendered text of the page state you drove to (results, cart, logged-in view) — no navigation. selector reads one element (a price, a table). |
| get_html | selector?, maxChars?=20000 (max 100000), session? | Fully rendered HTML (post-JS DOM) for structured extraction — tables, data attributes, JSON-LD. Scope with selector; truncated at maxChars. |
| screenshot | session? | Viewport PNG. Prefer snapshot for reading/acting — it's cheaper. |
Acting on pages
| Tool | Arguments | Description |
|---|---|---|
| click | ref, force?=false, fallback?=false, session? | Click by snapshot ref. Fails loudly naming any covering overlay; reports effect= navigation / dom-change / none. |
| type | ref, text, submit?=false, verify?=true, session? | Type into an input (cleared first, verified after). submit presses Enter. |
| select | ref, value, session? | Choose a <select> option by label or value. |
| press | key, ref?, session? | Press a key or combo ("Enter", "Escape", "Control+A"), optionally focusing an element first. |
| scroll | direction?=down, ref?, session? | Scroll the page or bring an element into view. |
Account
| Tool | Arguments | Description |
|---|---|---|
| get_credits | — | Remaining credit balance in MB for the authenticated account. Check before large jobs. |
Geo comparison
| Tool | Arguments | Description |
|---|---|---|
| compare_countries | url, countries, steps?=[], extract?, screenshot?=false | Replay a fixed flow across 2–5 exit countries in parallel (fresh session each) and compare — e.g. extract a price per country. For interactive flows, open one session per country instead. |
Billing & limits
Credits are denominated in MB of bandwidth. New accounts get a free trial of 1 GB, valid for 7 days.
Trial expiry zeroes what you can spend, not your balance. Once the 7 days are up,
every request fails with 402 even though the unused MB are still on the
account. /api/v1/credits/ reflects this: credits
(spendable) goes to 0 while balance keeps its value. Topping up restores
access to both.
What costs what
- Proxy traffic — metered on actual bandwidth.
/api/v1/proxies/only hands you connection details and charges nothing for the call itself, but it does require a non-zero balance. /api/v1/browsers/— 5 MB deducted up front per call, whether or not you use the session.- MCP and SDK browser sessions — metered on bandwidth like any other proxy traffic. Page reads, interactive sessions, and each country in a
compare_countriescall all consume credits; screenshots and media-heavy pages consume noticeably more. Agents can check the balance mid-run with theget_creditstool.
Running out
- In-flight proxy connections are dropped when the balance reaches zero.
- The REST API and MCP answer
402; the gateway answers407, which is indistinguishable from a wrong password, so check your balance before assuming the credentials are broken.
Track consumption on the History page. To add credits or extend a trial, contact us at hello@archonum.com — self-service top-up is not available yet.
Errors
| Status | Meaning |
|---|---|
| 400 | Malformed request body or missing required fields. |
| 401 | Missing or invalid API token — or the account has no API token at all, or its email is not verified. |
| 402 | Insufficient credits, including a lapsed trial with an unspent balance. Top up; do not re-authenticate. |
| 404 | No device matches the requested filters — usually a country with no healthy devices right now. Also returned by the MCP for an unknown or expired session id. |
| 413 | MCP request body above 4 MB. |
| 429 | OAuth dynamic client registration rate limit (30/hour). Reuse the registered client_id rather than registering per run. |
Gateway (HTTP / SOCKS5 / CDP)
The gateway speaks proxy status codes, not REST ones, and it is deliberately terse — it will not tell an unauthenticated caller why a request failed.
| Status | Meaning |
|---|---|
| 407 | Every credential problem collapses into this one code: wrong username, wrong token, unverified account, and an empty balance. Check /api/v1/credits/ before assuming the credentials are wrong. |
| 502 | No healthy device for the request — often a country filter that nothing currently matches — or the upstream device failed mid-request. Retry, or drop the country filter. |
| 503 | Returned by the gateway's own /health probe when no devices are available. |
Support
Questions, credit top-ups, higher limits, or a bug to report: hello@archonum.com. For SDK issues, the GitHub tracker is faster.
Versioning
The current version is v1. Always include the version prefix
in your URLs (/api/v1/...).
When a breaking change lands, it ships as a new prefix
(/api/v2/…) alongside the old one —
a version stays mounted until it is announced as retired, so an integration pinned to
v1 keeps working.