You send the URL, we bring back the page that answered 403: a residential IP, a real browser TLS fingerprint, a fresh exit on every refusal and a real browser when the site demands JavaScript. The answer carries the status, the attempts, the time and the cost, so you always know what happened.
Measured on 2026-11-11 by our own canary: 72 of 81 calls. Captcha demo pages are run but left out of the count, because interactive captchas are not solved.

403
A 403, a security check or a JavaScript challenge instead of the page, however clean the IP and whatever User-Agent you set.
200
88.9% of 81 calls to 27 protected targets came back as the real page: median 4.1 s, p95 28.8 s.
Our own canary, not a brochure figure: the same targets, 3 runs each. The run is repeated and every number on this page is regenerated from its file.
Generated from the canary run of 2026-11-11, 3 runs on the same targets. Interactive captcha pages are excluded.
| Anti-bot system | Success | Median time | Calls |
|---|---|---|---|
| Cloudflare | 100% | 8.9 s | 9 |
| DataDome | 91.7% | 10.4 s | 12 |
| Akamai | 75% | 2.4 s | 12 |
| PerimeterX / HUMAN | 100% | 1.8 s | 9 |
| Kasada | 100% | 16.1 s | 6 |
| F5 BIG-IP | 100% | 3.4 s | 6 |
| Imperva | 83.3% | 7.4 s | 6 |
| AWS WAF | 66.7% | 14.3 s | 6 |
| Amazon | 66.7% | 4.1 s | 3 |
| 66.7% | 7.5 s | 3 | |
| Other sites | 100% | 2.0 s | 6 |
| 100% | 1.7 s | 3 |
These numbers come from our own canary, a run we repeat on the same pages. Customer traffic is never part of it.
Latest run: 2026-11-11. 27 pages, 3 runs each: 81 calls, 72 real pages (88.9%).
Three products share the same residential network. The one to call depends on what the target does to your request.
The page refuses your client with a 403, a security check or a challenge: one call brings back the real response, any method, your own headers and body, a login or a cart kept on one exit, billed by the GB from a prepaid balance.
Your client already passes and you only need another IP: a residential exit on the same username grammar (country, state, city, session) over HTTP or SOCKS5.
You want the page as Markdown, text or JSON and have no use for the raw response, a POST or a cookie jar of your own.
Same engine behind three doors. Pick by what your code already speaks; the snippets are the ones the dashboard fills with your own credentials.
You can change your code: one JSON call in, one JSON answer out, no certificate to install.
POST https://app.quantumproxies.io/api/v1/scraper/unlock
curl -X POST https://app.quantumproxies.io/api/v1/scraper/unlock \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/", "country": "us"}'
You already have a scraper that speaks proxy: point it at the host and port with your unlocker user and password, and install the CA once.
http://unlock.quantumproxies.io:9000
# once: curl -o unlocker-ca.pem https://app.quantumproxies.io/api/v1/scraper/unlock/ca
curl --proxy http://unlock.quantumproxies.io:9000 \
--proxy-user "USER:PASS" \
--cacert unlocker-ca.pem \
https://example.com/
Proxy without a certificate: send the request to http://unlock/ through the proxy and name the target in the x-qp-url header.
http://unlock.quantumproxies.io:9000, then http://unlock/
curl --proxy http://unlock.quantumproxies.io:9000 \
--proxy-user "USER:PASS" \
-H "x-qp-url: https://example.com/" \
http://unlock/
On the REST call you can list what the browser does before the page is captured: click, type, scroll, wait.
Send up to 100 URLs in one batch and get a webhook when they finish.
You set how long a page stays cached. While it is cached, asking for the same page again costs nothing.
The docs carry two single-file clients, one for Node.js and one for Python, and a migration table for code written for another unlocker.
A walkthrough of the Web Unlocker page of the dashboard: buy GB, pick a way in and send the first request. In English, with subtitles.
The identity headers your client sends (User-Agent, Accept, Sec-Fetch-*) are replaced by a set that matches the TLS handshake of a real browser. Authorization, cookies, content type and custom headers pass through untouched.
A challenge or a 403 triggers a retry on a new exit under another browser fingerprint family, up to three TLS attempts, all inside one time budget: 60 seconds by default, up to 120 with timeout_ms.
When the TLS tier keeps being challenged, a real browser opens the page and answers the JavaScript challenge. With a sticky session the clearance it earns is kept and replayed on your next requests to that site.
The Web Unlocker API is for the pages a plain HTTP client cannot get: the ones where the anti-bot layer scores the TLS handshake and the HTTP/2 settings before it reads a single header. A fetch or requests call carries its runtime's signature whatever User-Agent it sets. The unlocker fixes that at the transport layer, retries on a fresh residential exit when the origin refuses, opens a real browser when JavaScript is demanded, and hands back the origin's raw response: any method, your own headers and body, a login or a cart held on one exit IP.
A rotating residential proxy changes where a request comes from. It does not change what the request looks like: the TLS handshake, the HTTP/2 frame order and the header set still say Python or Node, and modern bot walls score exactly that. A web unlocker rewrites the request into one a real browser would send, retries under a different fingerprint when the origin refuses it, and switches to a real browser when the origin demands JavaScript. You keep the proxy interface; the unlocker adds the judgement.
Every attempt leaves under a real browser TLS profile with the identity headers rewritten to match it, because a Chrome handshake carrying a Firefox User-Agent is a louder signal than either alone. Pin a profile (Chrome, Firefox, Safari, Safari iOS, Edge, Brave, or mobile Safari on the REST endpoint) when a site expects one; pin none and the retries rotate between Chrome, Firefox and Brave, so a site that has burned one handshake meets another. Authorization, Cookie, Content-Type and custom X-* headers are forwarded verbatim, and keepHeaders sends yours as they are when you replay a captured app request.
mode auto, the default, climbs the ladder: TLS tier first, a fresh exit on a refusal, the browser brought in when the site keeps challenging. mode tls never opens the browser; mode browser starts in it. format returns the body as html, markdown or text, and render png takes a screenshot. The whole call, retries and rendering included, fits in one budget of 60 seconds by default, up to 120 with timeout_ms, and max_bytes caps the traffic one call may move. The answer says which tier won (tier_served), lists every attempt with its tier, profile, exit country, outcome, milliseconds and bytes (attempt_log), and prints the cost in bytes and dollars at the price of your tier.
Every response is classified before it reaches you. The classifier reads what bot-defence systems sign their pages with and names both the system (Cloudflare, DataDome, Akamai, PerimeterX and others) and the class of block: js_challenge, captcha, access_denied, rate_limited, fingerprint, geo or timeout. On the REST endpoint a still-blocked page arrives as a 200 with blocked set to true and the page itself for inspection, or as a 424 target_blocked when you set fail_on_block. On the forward proxy the origin's status is relayed with the x-qp-unlocker-blocked header. Interactive captchas are not solved: they come back labelled captcha.
Pass a country, and a state or city where the network has them, to exit from that market. Leave it empty and the exit country is read from the target's top-level domain, then from your account's country, with the United States only as the last resort. A sticky session id keeps one exit IP across calls for 3 to 1,440 minutes, so a login, a cart or a paginated listing stays on one identity. The unlocker also remembers, per domain, which tier and fingerprint family passed recently and starts there next time, and it quarantines an exit a site has just refused instead of offering it to that site again.
The Web Unlocker runs on two exit pools: Premium on residential IPs and Mobile on 4G/5G carrier IPs, each with its own prepaid GB balance bought in the dashboard from 1 GB, by card, PayPal, crypto or account balance. Usage is measured in bytes moved, retries and browser renders included, and when a balance runs out the answer is a 402 with the link to top up instead of a silent failure. The price per GB of each tier is shown on the Web Unlocker page of the dashboard, next to the buy button. There is no subscription and no minimum term.
REST and proxy share one catalogue. Every error names its code and says whether it is worth retrying, whether it was billed and what to do next: no_credit (402) with the buy link, target_blocked (424) with the block class and the attempt log, rate_limited (429, 20 calls a minute and 10 in flight on pay-as-you-go, with Retry-After), render_failed and upstream_failed (503), timeout (504) when timeout_ms ran out. A 403 or 429 that carries a real page is not a block and is returned as such.
A web unlocker is a service that delivers an ordinary HTTP request to a bot-protected site the way a real browser would: from a residential IP, under a browser TLS fingerprint with matching headers, retrying on a fresh IP when refused and opening a real browser for JavaScript challenges. It returns the origin's raw response, with the attempts and the cost.
A proxy only changes the source IP. Your client's TLS handshake and header set still reveal an automated tool, and that is what modern bot walls score. The unlocker rewrites the request to match a browser, retries under another fingerprint when refused and escalates to a real browser when JavaScript is demanded. Residential proxies are the right buy when your client already passes.
It answers JavaScript challenges with a real browser and, inside a sticky session, keeps the clearance cookie for the next requests to that site. Interactive captchas that need a human, such as hCaptcha, reCAPTCHA or a click-to-verify box, are not solved: the response comes back labelled captcha, with the vendor named, and the traffic it moved is billed by the GB unless the dashboard states otherwise.
Creating the account is free and takes a minute, and the Web Unlocker page of the dashboard has a Test a URL box that shows status, attempts, time and cost of a call. Unlocker GB are prepaid per tier from 1 GB, and what the first test calls cost is written next to the box. The free residential trial covers plain residential proxies, not the unlocker.
Yes. The REST endpoint is a normal HTTPS POST that any language speaks; the tabs above carry the same curl, Python, Node.js, PHP and Go snippets the dashboard fills with your credentials. Scrapy, Playwright or any client with a proxy setting uses the CONNECT proxy, and direct mode works where a certificate cannot be installed.
Both, on one account and one balance. REST when you can change your code: JSON in, JSON out, no certificate. Proxy when your scraper already speaks proxy: host, port, user and password, with the CA installed once. Direct mode when you want the proxy without a certificate: send the request to http://unlock/ and name the target in x-qp-url.
It is never returned as a silent success. The REST endpoint sets blocked to true and names the block class and vendor next to the page, or answers 424 target_blocked when you set fail_on_block; the proxy relays the origin's status with x-qp-unlocker-blocked. The bytes moved are billed by the GB unless stated otherwise in the dashboard, and the attempt log shows what they bought.
Yes. Pass a session id, in the request body or in the proxy username, and every call with that id leaves from the same exit IP for 3 to 1,440 minutes. That is how a login, a shopping cart or a paginated listing stays on one identity instead of changing IP on every page.
Pass country, and state or city where the network has them, and the Premium tier exits from that market on residential IPs; the Mobile tier does the same on 4G/5G carrier IPs. Leave it empty and the exit is chosen from the target's top-level domain, then from your account's country, with the United States as the last resort.
Only for HTTPS through the CONNECT proxy, which terminates TLS to rewrite the request: download the CA once from the API with your key. Direct mode, where the target goes in the x-qp-url header, and the REST endpoint need no certificate at all.
Yes, on the REST call. Add a list of browser actions (click, type, scroll, wait) and the browser runs them in order before the page is captured.
Yes. A batch takes up to 100 URLs in one call, and a webhook tells you when they have finished.
Not while the page is cached. You choose the cache lifetime on the call: until it runs out, the same page is answered from the cache and costs nothing.
It is billed per GB moved, from a prepaid balance you buy in the dashboard for the tier you use, Premium on residential exits or Mobile on carrier exits, starting at 1 GB. Retries and browser renders count. The live price per GB is shown on the Web Unlocker page of the dashboard before you buy; there is no subscription and no minimum term.
Skip the marketing. QuantumProxies.io publishes a machine-readable site map, Markdown for every page, a free MCP server, and APIs billed from the same balance as your proxies.
Connect in one command: npx -y quantumproxies-mcp