API Reference

UnblockingAPI is a web unblocker API that fetches public URLs and returns clean HTML — with optional JavaScript rendering, geo-routing and smart wait strategies for dynamic pages.

Base URL
https://api.unblockingapi.com

Want to test requests directly in your browser? Open the interactive Swagger UI to explore endpoints and try them live with your API key.

Quick start

Grab your API key and make your first request:

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.unblockingapi.com/unblock?url=https://example.com"

Prefer hands-on help?

Our developers can help integrate UnblockingAPI into your existing application or scraper.

Get setup help

Authentication

Every request needs your API key, sent any one of these ways:

X-Api-Key: <key>headerrecommended
Authorization: Bearer <key>header
?key=<key>query parameterhandy for quick browser tests
# Header (recommended)
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.unblockingapi.com/unblock?url=https://example.com"

# Bearer token
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.unblockingapi.com/unblock?url=https://example.com"

# Query parameter
curl "https://api.unblockingapi.com/unblock?url=https://example.com&key=YOUR_API_KEY"

Rate limits

Rate limits depend on your plan and are enforced per API key.

Each plan includes:

  • a monthly credit allowance — one successful request costs 1 credit
  • a concurrent request limit
  • fair use and abuse prevention controls

Exceeding your concurrency limit returns 429; running out of credits returns 402. See Pricing for current plan limits.

Some plans may also include short-window burst limits to protect reliability.

/unblock

Fetch a public URL and get clean HTML back. Both GET and POST are supported — POST takes a JSON body with the same fields.

GETPOST/unblock
# GET request
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.unblockingapi.com/unblock?url=https://example.com"

# POST request
curl -X POST \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "render": true}' \
  "https://api.unblockingapi.com/unblock"

Parameters

urlstringrequired

URL to fetch. Must be http(s) and not point at a media/binary file.

renderbooleandefault: false

Render with a real browser (executes JavaScript). Required for the wait options. Slower than a plain fetch — try without it first, and only enable it if the response is missing content. Renders fetch the document and the scripts that build it; CSS, images and fonts are always skipped, since they only add transfer time for bytes that never reach your response.

locationstring

2-letter country code for geo-routing where supported. Examples: us, gb, de.

wait_forstringdefault: stable

When to capture the page (requires render=true). One of stable — capture once the DOM stops changing, domcontentloaded — capture immediately, networkidle — wait for the network to go quiet, or any CSS selector, which waits for that element to become visible and then settles. See Waiting for content.

settle_msintegerdefault: 5000

Ceiling on the settle wait — not a fixed delay. Max 25000. Applies to stable and selector waits.

wait_rulesarray

Conditional waits for pages with more than one possible layout. Each if selector is probed in order; the first visible one wins and its then replaces wait_for.

detect_msintegerdefault: 800

How long to probe wait_rules guards before falling back to wait_for. Max 25000.

max_ageintegerdefault: 0

Opt-in response cache. Accept a previously fetched copy of the same page, up to this many seconds old, instead of fetching again. Max 300. A hit returns in milliseconds and carries cached: true. Worth it when you poll the same URLs on a fixed interval. Leave it at 0 and every request fetches fresh — nothing is cached, read or written unless you ask.

templatestring

Parse the page with a named template and return structured JSON instead of HTML. Takes a reference like rasmus/cafes. The template supplies the fetch settings its parser needs, which override the ones you send. See Templates.

remove_scriptsbooleandefault: true

Strip <script> tags. On by default. Scripts are removed in the render worker before the page is sent back, so this also cuts transfer time.

remove_stylesheetsbooleandefault: true

Strip <style> tags and stylesheet links. On by default, and removed in the render worker. Inline style attributes are always kept.

remove_svgsbooleandefault: true

Strip <svg> tags from the returned HTML. On by default.

Response format

Every response follows the same envelope:

{
  "job_id": "abc123",
  "url": "https://example.com",
  "status": "succeeded",
  "http_response_code": 200,
  "response_time_ms": 1250,
  "render": false,
  "location": "de",
  "response_format": "html",
  "response": "<!doctype html>..."
}
job_idstring

Unique ID for this request.

urlstring

The URL that was fetched.

status"succeeded" | "failed"

"succeeded" for 2xx and 404 targets; "failed" otherwise.

http_response_codeinteger

The target's actual HTTP status code. On a 500 response, this holds the real upstream code (e.g. 403, 429).

response_time_msinteger

Time taken in milliseconds.

renderboolean

Whether browser rendering was used.

locationstring | null

Country code used, or null.

response_format"html" | "json"

"html" normally, "json" when you named a template and its parser ran.

responsestring | object

The HTML as a string, or the parsed object when a template ran.

api_namestring

Present only when you named a template. The template that answered.

parse_errorboolean

Present (true) only when a template’s parser failed and you got raw HTML instead. See Templates.

cachedboolean

Present (true) only when max_age was set and the response came from the cache. A hit still costs one credit.

errorstring

Present only when status is "failed".

Waiting for content

Dynamic pages finish loading long after the HTML arrives. These options say when to capture. All require render=true.

wait_for

stabledefault

Capture once the DOM stops changing. Best default for most pages — it adapts to whatever the page is doing instead of guessing a duration.

domcontentloadedfastest

Capture immediately. Use when the content you want is in the initial HTML.

networkidlestring

Wait for the network to go quiet. Avoid on pages that poll — see the note below.

<css selector>string

Any other value is treated as a CSS selector: wait for that element to become visible, then settle. The most precise option when you know what you are looking for.

On pages that never go quiet — live scores, tickers, chat, polling widgets — networkidle will wait out its whole budget and return no sooner than the timeout. Prefer stable or a selector.

settle_ms — a ceiling, not a delay

Settling watches the page and captures as soon as nothing in the DOM has changed for 500 ms; every change restarts that window. A page that goes quiet after 900 ms comes back after 900 ms — settle_ms only caps how long that can take. Reaching it means the page never stopped changing, and it is captured as it is.

Raise it for pages that keep streaming content in (infinite scroll, lazily loaded sections); lower it to bound the worst case. It applies to stable and to selector waits, and is ignored for domcontentloaded and networkidle.

wait_rules — one request, several layouts

Some pages serve more than one layout: a consent gate, an interstitial, an A/B variant, a logged-out fallback. Rather than guessing which you will get, describe each one. Every if selector is probed in list order for up to detect_ms; the first one that is visible wins, and its then replaces wait_for for that request. If nothing matches, wait_for is used as normal.

An empty then means “this layout matched, capture it now”.

Examples

// Wait for results to become visible, then settle
{ "url": "https://example.com/search?q=shoes", "render": true, "wait_for": "#results" }

// A page that keeps loading content in — allow longer to go quiet
{ "url": "https://example.com/feed", "render": true,
  "wait_for": "stable", "settle_ms": 12000 }

// Two possible layouts: a consent gate, or the results directly
{ "url": "https://example.com/search?q=shoes", "render": true,
  "wait_for": "#results",
  "wait_rules": [{ "if": "#consent-gate", "then": "#results" }],
  "detect_ms": 800 }

On a GET, pass wait_rules as a JSON string.

Error codes

200

Success — the target returned a 2xx. Body carries the fetched content.

401

Missing or invalid API key.

404

Target returned 404. Treated as a successful result (status is "succeeded"), not a failure.

402

Out of credits. Top up or upgrade your plan to resume.

422

Invalid parameters — check the error message for details.

429

Concurrency limit exceeded. Back off and retry.

500

Request failed due to an upstream error, block, captcha challenge or render failure. Check http_response_code and error for details.

503

Service temporarily unavailable — proxy pool exhausted or render backend saturated. Retry shortly.

504

Timed out waiting for the target or render backend.

Working on a tricky target? Talk to us — we can help tune routing, rendering and request strategy for your use case.

Templates

A template turns one kind of page into clean JSON. Name one on your request and you get parsed fields back instead of HTML, from the same /unblock endpoint, with the same key and the same cost.

Templates are unlimited on every plan, the free one included. There is no approval step and no separate endpoint.

Naming one

Pass template with the template’s reference, which is its author’s handle and its slug. Nothing is ever applied unless you ask for it — omit the parameter and the same URL returns plain HTML, whatever templates exist for that site.

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.unblockingapi.com/unblock?url=https://example.com/listing&template=rasmus/cafes"

The template also supplies the fetch settings its parser needs, and those win over yours — a template built against a JavaScript-rendered page will render whether or not you asked for it, and is billed like any render. The response names the template in api_name and sets response_format to json, so response is an object rather than a string.

{
  "job_id": 86,
  "url": "https://example.com/listing",
  "status": "succeeded",
  "http_response_code": 200,
  "response_time_ms": 812,
  "render": true,
  "location": "se",
  "response_format": "json",
  "api_name": "cafes",
  "response": {
    "title": "Kafé Esaias",
    "address": "Stora Nygatan 21",
    "rating": 4.6
  }
}

When something goes wrong

A template is a reading of someone else’s markup, and markup changes. So a parser that breaks never costs you the response: you get the raw HTML back with parse_error: true and response_format back to html, rather than an error. Check that flag if you parse strictly.

A name that does not resolve is a 404, which covers both an unknown template and a private one belonging to somebody else. If the target itself answers with a non-2xx, the page is returned unparsed and still tagged with api_name — there was no page to read.

Where templates come from

You build them. Open a page in the editor, tap the things you want, and it writes a template that returns them. Publish it and it appears in the template library, where anyone can open, fork or call it — and you earn credits when a paying customer calls yours. The API reference lists every published template with the site it is built for.

Use must comply with the Acceptable Use Policy.

Open-source MCP server

@unblockingapi/mcp exposes this API to AI agents over MCP. Source and package are public.

Ready to start?

Get your API key and make your first request in seconds.

Get API key