Requests that arrive as locals.
bytetourist is a proxy and crawling API. Every request leaves through an edge we run (a datacenter machine or a home connection) with a real browser’s fingerprint, at a pace the site will accept.
India-first: datacenter and residential edges for sites that turn foreign or cloud traffic away.
curl -k https://example.com \
-x http://dev.bytetourist.com:8080 \
-U "$BT_KEY-cc-in:" \
-H "X-Proxy-Stealth: safari_ios"-cc-in picks an Indian IP. The -k is there because the proxy re-signs HTTPS to route each request.Steer every request
Point any HTTP client at the proxy with your API key as the username. Routing options ride along in the username, so they work the same for HTTP and HTTPS. Per-request options are headers. None of it reaches the site.
In the username, after your key
cc-in- The edge’s country, as an ISO code: in, us, de.
iptype-residentialdatacenterorresidential.session-abc- Any token. With
strategy-session_affinity, requests that share it stay on the same edge while it’s available. strict-true- Fail instead of falling back to any edge when none matches.
strategy-goodput_per_second- How the edge is picked. This one, which favours edges by pages delivered per second, is the default.
For example, $BT_KEY-cc-in-iptype-residential
As request headers
X-Proxy-Stealth- The browser identity:
chrome_desktop,chrome_android,firefox_desktop,safari_desktoporsafari_ios. Leave it out and we choose one per site, skipping identities that site has been refusing. X-Proxy-Insecuretrueskips checking the site’s own certificate, for origins with expired or self-signed ones.X-Proxy-Reusetruekeeps the connection to the site open between requests;falsegives each request a fresh TLS handshake.
Proxy-side failures carry a stable X-Proxy-Error slug, like no_edge or governor_throttle, so your client can tell “retry” from “give up”.
curl -X POST \
https://dev.bytetourist.com/v1/fetch \
-H "Authorization: Bearer $BT_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com"
}'Papers that agree with themselves
Anti-bot systems don’t just read your User-Agent. They compare it with the TLS handshake, the HTTP/2 settings, the client hints and the order of your headers. A Chrome handshake under a Firefox User-Agent is the giveaway.
Each bytetourist identity is one browser, top to bottom, and for Chrome and Firefox every part derives from a single version number, so the parts can’t drift apart.
- Type
- P
- Issued by
- bytetourist
- Identity
- chrome_desktop
- Handshake (TLS + HTTP/2)
- chrome_146
- User-Agent
- Chrome 146 on Windows
- Client hints
- Sent:platform "Windows",mobile ?0
- Header order
- sec-ch-ua,sec-ch-ua-mobile,sec-ch-ua-platform,Upgrade-Insecure-Requests,User-Agent,…
- Accept-Language
- en-US,en;q=0.9
Handshake, User-Agent, client hints and header order all describe the same browser.
Hand us a URL. We’ll walk the site.
A crawl starts from one URL and follows the links on that host, breadth-first, up to your page and depth limits, through the same edges. Pages are saved in batches as zstd-compressed JSON lines.
Pause or cancel a running crawl; resume a paused one. Already have a sitemap? Send the URLs and skip discovery.
- Render JavaScript
- The page as a browser sees it after scripts run. The browser runs on our side, but every request it makes still leaves through an edge.
- Screenshot
- A full-page PNG alongside the rendered DOM.
Crawl
- From
- example.com
- Pages
- up to1,000
- Depth
- 5
- Subdomains
- no
- Render JavaScript
- yes
- Saved as
- zstd JSON lines
curl -X POST \
https://dev.bytetourist.com/v1/crawls \
-H "Authorization: Bearer $BT_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"maxPages": 1000,
"renderJs": true
}'{
"crawl_id": "crawl_…",
"url": "https://example.com/about",
"status_code": 200,
"fetched_at": "2026-09-26T09:14:03.512Z",
"depth": 1,
"headers": { … },
"body": "<!doctype html>…"
}Transparent Pricing
1 credit: Fetch, or one crawled page
6 credits: A crawled page rendered with JavaScript
6 credits: A full-page screenshot of a crawled page, with its DOM
+1 credit: Structured extraction (preview)
+1 credit: Each 5 MiB of response body on a proxied request
You’re charged once a response arrives, even if the site answers 404 or 429. If we fail before the site answers (no edge, a timeout, our own throttle), it’s free.
A render counts once, however many scripts and images the page loads.
A crawl retries pages that fail, and each attempt that gets a response is charged.
| Plan | Credits | At once |
|---|---|---|
| Basic | 5,000 a month | up to 10 requests |
| Pro | 100,000 a month | up to 200 |
| Enterprise | By agreement | up to 2,000 |
Unused monthly credits carry over.
| Credits | Price |
|---|---|
| 5,000 | $16 |
| 100,000 | $83 |
| 500,000 | $333 |
Packs never expire.
