Resources
One request, in three languages
There is one call worth learning and everything else is a variation on it. This page describes it precisely enough to type from memory in whatever language you already use, with no client library and no framework.
What we do not offer
There is no package to install. A Python client and a JavaScript client exist in our repository, but neither is published to PyPI or npm, so any instruction to pip install or npm install one of them would be a line that fails when you paste it. Use your language's ordinary HTTP client — that is what the examples below assume. There is also no headless browser and no HTML parsing service: we hand you the response, and what you do to it is yours.
The call, field by field
Every example below is the same HTTP request. Get this right once and the rest is your own error handling.
Method and URL
POST to https://api.roamingproxy.com/v2/proxy/fetch. The region is a query parameter on that URL, not a body field: ?region=europe, or us-east, or us-west.
Headers
x-api-key with your rp_ key, and Content-Type: application/json. Authorization: Bearer works too; if you send both, x-api-key is the one used.
Body
A JSON object with one required field: {"url": "https://example.com"}. Nothing else is required.
Optional header worth sending
Idempotency-Key, any unique string up to 128 characters, makes the request safe to retry after a timeout.
curl
Put your key in an environment variable first, so it never lands in your shell history or a committed file. Then: curl with -X POST against the fetch URL with ?region=europe appended, -H for the x-api-key header reading $RP_API_KEY, -H for the JSON content type, and -d carrying the JSON body with your url in it. Pipe the output through jq if you want to look at one field at a time rather than a whole page of HTML.
That single command is the entire integration test for a new account. If it returns an envelope, your key works, your scope is right and the region is in service.
Python, with requests
Import requests and os. Call requests.post with the fetch URL, params set to {"region": "europe"}, headers set to {"x-api-key": os.environ["RP_API_KEY"]}, and json set to {"url": "https://example.com"}. Passing params rather than string-concatenating the query means requests escapes it for you, and passing json rather than data sets the content type for you.
Read the reply with response.json(). Check the envelope's own HTTP status first to learn whether we served you, then read the status field inside the JSON to learn what the target said. Those are two different numbers and conflating them is the most common integration bug we see.
JavaScript, with fetch
Node 18 and every current browser runtime have fetch built in, so there is nothing to install. Call fetch with the URL including ?region=europe, method POST, a headers object carrying x-api-key and content-type: application/json, and body set to JSON.stringify of an object with your url in it. Await response.json() and read the same fields.
Keep the key on the server. A key shipped to a browser is a key anyone can read, and ours are scoped rather than anonymous, so the bill is yours.
What comes back
The envelope is flat and every field is documented in the reference. These are the ones you will actually branch on.
result
The response body the target returned, as a string.
status
The HTTP status the TARGET answered with. This is the field that tells you whether you were blocked.
region_used
The region that actually served the fetch. Normally the one you asked for; worth logging so you can tell when it is not.
public_ip and device_id
The address the target saw, and which node served it. Both are what a support report needs.
final_url and redirects
Where the fetch ended up and how many hops it took. Compare final_url with what you asked for before trusting the body.
content_type, bytes, elapsed_ms
The target's content type verbatim, the body size the node measured, and the milliseconds the node spent fetching.
The other endpoints
GET /v2/proxy/regions returns the regions that can serve right now. GET /v2/proxy/status reports fleet health. GET /v2/user-agents/ returns the user-agent catalog you can pick a string from.
All three take the same header — x-api-key — but not the same scope. The two /v2/proxy/ endpoints need the proxy scope; the catalog needs read. A key carrying both calls all three. A proxy-only key gets missing_scope on the catalog, so check what your key was minted with before you wire these into a start-up check, or that check will hard-fail boot on the one call that fetches nothing.
Ready-made versions of all of this
The dashboard at https://cloud.roamingproxy.com has an integrations page with copy-paste snippets in curl, Python and Node, already filled in with the right base URL.
There is a Postman collection, generated from the live OpenAPI document rather than hand-maintained, so it cannot drift from the real API. You can also point Postman or Insomnia straight at https://api.roamingproxy.com/v2/docs/openapi.json and skip the file entirely.
There is an MCP server, so an agent in Claude, Cursor or any other MCP client can fetch pages and compare regions through your account, with the key living in the server's environment instead of in a tool argument. It is not on a public registry yet, so setting it up means building it from source once; email support@roamingproxy.com and we will send you the package.
Questions
- Why is region a query parameter and not part of the body?
- Because it selects which node serves the request rather than describing what to fetch, and putting it in the URL makes it visible in a log line and easy to vary in a client that caches the body. Sending it in the body instead produces a 422.
- Can I copy an example that uses one of your SDKs?
- Not from here. The Python and JavaScript clients exist but are unpublished, so an install line for either would fail. Everything on this page uses the standard library or the most ordinary HTTP client in the language, which is also what you should reach for in production.
- How do I send custom headers to the target?
- You do not, today. The body takes a url. If your target needs a specific header to answer usefully, email support@roamingproxy.com and describe it, so the request shape grows for a reason we can point at rather than speculatively.
- What is the smallest useful error handler?
- Read the code field on any non-2xx envelope. Retry with backoff on no_healthy_endpoints and upstream_unavailable, wait Retry-After on rate_limited and target_rate_limited, and treat target_not_permitted, unknown_region and missing_scope as bugs in your request rather than transient failures.
Get a key
Create an account and mint an API key in the dashboard. The full endpoint reference — request shapes, parameters and error codes — is published at https://api.roamingproxy.com/v2/docs.
