QuanticData API (2026-10-20)
Scrape, search, crawl, unlock, run collectors and build datasets — one host, one Bearer key, one JSON envelope.
This specification is generated from the application source (route handlers, auth middleware, billing config). Every endpoint answers the same envelope: {"type":"response","message":"…","payload":{…}} on success and {"type":"error","message":"…","payload":{…}} on failure. Data API calls are pay-per-success: a blocked page, a target 4xx/5xx, a timeout or an error on our side is never charged. The Web Unlocker is the exception: it spends prepaid GB on all the traffic it moves, blocked pages included (see its section). Billed responses carry payload.usage (cost_usd, free_usd, paid_usd, balance). Prices are referenced by key (x-price-key) and resolved from pricing.json; rate limits per tier live in tiers.json. Brand placeholders (quanticdata.io, QuanticData) are resolved from brands.json.
Every request carries an API key in the Authorization header:
Authorization: Bearer qd_live_…
Authorization: Bearer qd_live_YOUR_API_KEY. Keys are qd_live_/qp_live_ followed by 64 hex characters and are created on the dashboard API keys page. Only this header is read: there is no x-api-key fallback and keys are never accepted in the query string. A disabled, expired or unknown key, or a banned account, answers 401.
Keys are created on the API keys page of the dashboard; register if you do not have an account. Keys are shown once; keep them in an environment variable, never in client-side code.
Base URL: https://api.quanticdata.io/v1 (same API on the dashboard host: https://app.quanticdata.io/api/v1, without the short aliases).
Machine-readable formats: openapi.json · openapi.yaml · index.md (this reference as Markdown) · llms.txt.
Four calls take a script or an agent from an API key to working proxies, paid from the wallet balance. Top up the balance in the dashboard first: the API pays from the balance only (0% VAT).
| Step | Call | What you keep |
|---|---|---|
| 1. Pick a plan | GET /public/plans?planType=residentialpremium |
plans[].id, amount (USD) |
| 2. Check the balance | GET /public/balance |
balance (USD) |
| 3. Buy | POST /public/purchase with {"planId": "…"} |
order.id |
| 4. Get proxy lines | POST /public/proxies/generate with {"orderId": "…"} |
proxies[] |
| 5. Use them | any HTTP client |
The purchase charges the balance and activates the plan in the same call. Responses to handle: 400 Insufficient balance (nothing charged, top up), 422 NOT_DELIVERED_REFUNDED (not delivered, the amount is back on the balance, buy again), 409 PAYMENT_UNDER_REVIEW (do not buy again, contact support). Do not resend a purchase that timed out: look for it in GET /public/orders first. Location values for step 4 (state, city, ISP slugs) come from the endpoints under Proxy locations.
API=https://api.quanticdata.io/v1
KEY=qd_live_YOUR_API_KEY
# 1. plans of one type, cheapest first
curl -s "$API/public/plans?planType=residentialpremium" -H "Authorization: Bearer $KEY"
# 2. balance
curl -s "$API/public/balance" -H "Authorization: Bearer $KEY"
# 3. buy: charges the balance, returns order.id
curl -s -X POST "$API/public/purchase" -H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" -d '{"planId":"PLAN_ID"}'
# 4. two sticky US lines, same IP for 10 minutes each
curl -s -X POST "$API/public/proxies/generate" -H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"orderId":"ORDER_ID","country":"us","rotation":"sticky","sessionTime":10,"quantity":2,"format":"http://user:pass@host:port"}'
# 5. use a line
curl -x "PROXY_LINE" https://ipinfo.io/json
The same flow in Python, stopping before the purchase when the balance is too low:
import os
import requests
API = "https://api.quanticdata.io/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
def call(method, path, **kwargs):
r = requests.request(method, API + path, headers=HEADERS, timeout=120, **kwargs)
body = r.json()
if body.get("type") == "error":
raise RuntimeError(f"{r.status_code} {body['message']} {body.get('payload')}")
return body["payload"]
plans = call("GET", "/public/plans", params={"planType": "residentialpremium"})["plans"]
plan = min(plans, key=lambda p: p["bandwidthGB"])
if call("GET", "/public/balance")["balance"] < plan["amount"]:
raise SystemExit("Top up the balance in the dashboard first.")
order_id = call("POST", "/public/purchase", json={"planId": plan["id"]})["order"]["id"]
lines = call("POST", "/public/proxies/generate", json={
"orderId": order_id, "country": "us", "rotation": "sticky",
"sessionTime": 10, "quantity": 2, "format": "http://user:pass@host:port",
})["proxies"]
proxy = lines[0]
print(requests.get("https://ipinfo.io/json", proxies={"http": proxy, "https": proxy}, timeout=30).json())
Keep order_id: it is the plan's id for later generate and whitelist calls (GET /public/proxies lists it with the bandwidth left). Buying again creates a new plan with new credentials; adding GB or renewing is done in the dashboard. Premium ISP dedicated IPs follow their own flow with an Idempotency-Key (see Premium ISP).
Status codes used by this API and what each one means (collected from every endpoint below). Error bodies are JSON with type: "error"; read message for the reason.
| Status | Meaning | Returned by |
|---|---|---|
400 |
Malformed input. message names the parameter and the rule it broke. |
52 endpoints |
401 |
Missing, malformed, unknown, disabled or expired API key; or the account is not active. | 80 endpoints |
402 |
The free tier plus wallet balance cannot cover the worst-case estimate of this call, or the account's monthly spend cap is reached. Nothing was run or charged. | 17 endpoints |
402 |
The wallet balance cannot cover the total. Nothing was created or charged: top up in the dashboard and send the request again. | POST /public/ipv6/orders |
402 |
The wallet balance cannot cover the total. Nothing was created or charged: top up in the dashboard and send the request again. | POST /public/premium-isp/orders, POST /public/premium-isp/orders/{orderId}/renewal |
403 |
No exit pool for the requested tier (e.g. no mobile unlocker GB on the account). | 20 endpoints |
403 |
No proxy pool is available to serve the call (no house plan and no residential/datacenter/IPv6 plan on the account). | 10 endpoints |
403 |
Your own API key is required (keyless and pay-per-call access cannot buy), or the key was created by a connected app and cannot spend the balance. | GET /public/ipv6/plans, POST /public/ipv6/quote, GET /public/ipv6/orders, POST /public/ipv6/orders, GET /public/ipv6/orders/{orderId} |
403 |
The plan was disabled by support: it is no longer listed by GET /public/proxies and its credentials, endpoints and whitelist are not handed out. Contact support. |
POST /public/proxies/generate, GET /public/proxies/whitelist-ip, POST /public/proxies/whitelist-ip, DELETE /public/proxies/whitelist-ip |
404 |
presetId does not resolve to one of your presets. |
41 endpoints |
409 |
The selection cannot be sold right now, or the request conflicts with an earlier one. Nothing was charged unless the code says so. | 9 endpoints |
409 |
The cell is not sold, the price moved above your maxTotal, the Idempotency-Key was reused for another body, the checkout is closed, or the payment needs a human look. Nothing was charged unless the message says otherwise. |
POST /public/ipv6/quote, POST /public/ipv6/orders |
409 |
This plan type has no rotation in place (ROTATION_NOT_SUPPORTED). reason: new_string_only — request a new sticky string with generate; static_ips — ISP plans have dedicated static IPs; gateway_managed — the gateway assigns the IP. Also LINK_LIMIT_REACHED on link creation (1,000 active links per plan). |
POST /public/proxies/{orderId}/rotate, GET /public/proxies/{orderId}/rotation-links, POST /public/proxies/{orderId}/rotation-links, DELETE /public/proxies/{orderId}/rotation-links/{linkId}, GET /public/rotate/{token}, POST /public/rotate/{token} |
410 |
PLAN_EXPIRED: the plan has expired. |
POST /public/proxies/{orderId}/rotate, POST /public/proxies/{orderId}/rotation-links, GET /public/rotate/{token}, POST /public/rotate/{token} |
422 |
Input that can never resolve (documentation placeholder, undelegated TLD) — before or after the run; retrying the same input cannot help. Not billed. | POST /scraper/collectors/{slug}/run, POST /public/premium-isp/orders, POST /public/purchase, POST /scraper/video |
422 |
The plan could not be delivered and the amount is back on your balance: you have not been charged. Send the purchase again with a new Idempotency-Key. | POST /public/ipv6/orders |
424 |
The run failed at the source (blocked, timed out, layout changed). JSON body with run_id and error; not billed, safe to retry. |
POST /scraper/collectors/{slug}/run |
429 |
Key rate limit (hourly window), plan per-minute budget, browser-render concurrency, or pool capacity. Back off on Retry-After. | 79 endpoints |
429 |
RATE_LIMITED: one rotation every 10 seconds per session (scope: session), 1,200 rotations an hour per account (scope: account), or too many unknown links from one address (scope: ip, link only). API-key calls also count against the key's hourly window. Back off on Retry-After. |
POST /public/proxies/{orderId}/rotate, GET /public/rotate/{token}, POST /public/rotate/{token} |
500 |
Extraction failed on our side or timed out (70 s budget). Never billed. | 44 endpoints |
502 |
Only with failOnBlock: true: every tier came back blocked. Same diagnostics as the 200 form; the GB moved are debited. |
8 endpoints |
503 |
The Data API group is switched off for non-admin keys (early-access kill switch). | 40 endpoints |
503 |
IPv6 speed plans are not available through the API on this account yet, the grid cannot be read right now, or balance payments are switched off. Retry after the Retry-After seconds. |
GET /public/ipv6/plans, POST /public/ipv6/quote, GET /public/ipv6/orders, POST /public/ipv6/orders, GET /public/ipv6/orders/{orderId} |
503 |
Premium ISP is not available through the API on this account yet, a price or the catalog cannot be read right now, or balance payments are switched off. Retry after the Retry-After seconds. |
11 endpoints |
503 |
SERVICE_UNAVAILABLE: rotation is temporarily unavailable. Retry after Retry-After. |
POST /public/proxies/{orderId}/rotate, GET /public/proxies/{orderId}/rotation-links, POST /public/proxies/{orderId}/rotation-links, DELETE /public/proxies/{orderId}/rotation-links/{linkId}, GET /public/rotate/{token}, POST /public/rotate/{token} |
504 |
The read timed out. Pass start/end to read a shorter window. Not billed. |
POST /scraper/video |
Response headers related to limits: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After, X-RateLimit-Scope, X-RateLimit-Plan.
Limits per tier (live values as of 2026-10-19):
| Tier | Monthly | Free usage / month | Requests / minute | Batch concurrency | Unit price discount |
|---|---|---|---|---|---|
| Pay as you go | $0 | $2 | 20 | 5 | 0% |
| Starter | $19/month | $15 | 300 | 10 | 10% |
| Growth | $79/month | $50 | 600 | 20 | 20% |
| Scale | $299/month | $250 | 1200 | 20 | 30% |
- Per API key. Two windows apply: the tier's requests/minute (tiers.json → rateLimitPerMin) and an hourly window of max(1000, rateLimitPerMin × 60). The hourly window counts every call made with the key, on every endpoint: Data API, proxy, plan and Premium ISP calls share one counter, so a large scraping job can use up the hour your proxy scripts need. The per-minute budget is per account and counts write calls (POST, PUT, PATCH, DELETE) only. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (hourly window); a 429 also carries Retry-After. Plan-level limiters (per-minute budget, browser-render concurrency) add X-RateLimit-Scope and X-RateLimit-Plan to their 429s.
- rateLimitPerMin is enforced per API key; the key also has an hourly window = max(1000, rateLimitPerMin × 60) requests.
- A pay-as-you-go account in real-balance billing mode gets balance_mode_rate_limit_per_min (pricing.json) instead of its tier cap.
- 429 responses carry X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and Retry-After.
- Real-balance billing mode: 300 requests/minute instead of the tier cap.
Every pay-as-you-go account includes $2 of free usage per month. Only successful calls are billed; a blocked page, a target 4xx/5xx, a timeout or an error on our side costs nothing. Prices below are the list of 2026-10-19; GET /scraper/billing returns the live list applied to your key. LLM tokens used by the AI endpoints are billed at provider cost × 2.
| Endpoint | Price keys |
|---|---|
POST /scraper/extract |
extract $0.0015 per call + $3/GB, max $0.02 per callextract_render $0.0025 per call + $4/GB, max $0.05 per callai_extract $0.005 per call, max $1.50 per call |
POST /scraper/serp |
serp $0.0009 per callserp_render $0.002 per call |
POST /scraper/serp/bulk |
serp_render $0.002 per callserp $0.0009 per call |
POST /scraper/map |
map $0.003 per call |
POST /scraper/crawl |
crawl_page $0.0003 per callextract_render $0.0025 per call + $4/GB, max $0.05 per call |
POST /scraper/batch |
batch_url $0.0004 per callextract_render $0.0025 per call + $4/GB, max $0.05 per call |
POST /scraper/unlock |
unlock_request $2.40/GB of transferred data |
POST /scraper/ai |
ai_extract $0.005 per call, max $1.50 per callextract $0.0015 per call + $3/GB, max $0.02 per callserp $0.0009 per callmap $0.003 per call |
POST /scraper/places-ai |
places_ai $0.005 per call, max $3 per callserp_render $0.002 per call |
POST /scraper/shopping-ai |
shopping_ai $0.005 per call, max $3 per callserp_render $0.002 per call |
POST /scraper/ai-visibility |
ai_visibility $0.01 per callai_visibility_citation $0.01 per callserp $0.0009 per call |
POST /scraper/seo-audit |
seo_audit $0.003 per callextract $0.0015 per call + $3/GB, max $0.02 per call |
POST /scraper/collectors/{slug}/run |
collector_result — by collector, table below |
POST /scraper/datasets |
dataset_row $0.03 per calldataset_row_refresh $0.01 per call |
POST /scraper/parser/generate |
parser_generate $0.02 per call |
POST /scraper/parser/presets/{id}/heal |
parser_generate $0.02 per call |
POST /scraper/video |
video $0.02 per call |
Collector results (POST /scraper/collectors/{slug}/run, per delivered result): |
| Collector price key | Per delivered result |
|---|---|
collector_ai_readiness |
$0.003 |
collector_airbnb_stays |
$0.001 |
collector_aliexpress_search |
$0.001 |
collector_amazon_product |
$0.008 |
collector_amazon_reviews |
$0.002 |
collector_amazon_search |
$0.001 |
collector_app_store_apps |
$0.0008 |
collector_app_store_reviews |
$0.0005 |
collector_arxiv_papers |
$0.0004 |
collector_asos_search |
$0.001 |
collector_autotrader_search |
$0.001 |
collector_bbb_businesses |
$0.002 |
collector_bestbuy_product |
$0.002 |
collector_booking_stays |
$0.02 |
collector_business_directory |
$0.001 |
collector_capterra_products |
$0.01 |
collector_carvana_cars |
$0.001 |
collector_certificate_transparency |
$0.0004 |
collector_clinical_trials |
$0.0005 |
collector_coingecko_coins |
$0.0002 |
collector_company_profile |
$0.03 |
collector_coursera_courses |
$0.001 |
collector_crates_io |
$0.0003 |
collector_defillama |
$0.0003 |
collector_dns_records |
$0.001 |
collector_docker_hub |
$0.001 |
collector_doordash_restaurants |
$0.003 |
collector_ebay_catalog |
$0.006 |
collector_ebay_product |
$0.006 |
collector_ebay_search |
$0.003 |
collector_exchange_rates |
$0.0002 |
collector_flipkart_search |
$0.001 |
collector_g2_products |
$0.001 |
collector_github_repos |
$0.0005 |
collector_gleif_lei |
$0.0004 |
collector_google_autocomplete |
$0.0002 |
collector_google_events |
$0.002 |
collector_google_flights |
$0.003 |
collector_google_jobs |
$0.001 |
collector_google_lens |
$0.004 |
collector_google_maps_places |
$0.001 |
collector_google_news |
$0.0005 |
collector_google_play_apps |
$0.006 |
collector_google_shopping |
$0.001 |
collector_google_trends |
$0.0005 |
collector_hacker_news |
$0.0003 |
collector_healthgrades_doctors |
$0.001 |
collector_hotels |
$0.02 |
collector_idealista_search |
$0.001 |
collector_indeed_jobs |
$0.001 |
collector_instagram_profile |
$0.006 |
collector_itunes_search |
$0.0004 |
collector_keyword_ideas |
$0.0002 |
collector_kleinanzeigen_search |
$0.001 |
collector_linkedin_company |
$0.005 |
collector_linkedin_jobs |
$0.001 |
collector_linkedin_profile |
$0.005 |
collector_local_business_leads |
$0.01 |
collector_marketwatch_quote |
$0.003 |
collector_miodottore_doctors |
$0.001 |
collector_nike_products |
$0.001 |
collector_npm_packages |
$0.0003 |
collector_nvd_cve |
$0.0004 |
collector_openalex |
$0.0004 |
collector_openfda |
$0.0004 |
collector_openlibrary_books |
$0.0004 |
collector_paginegialle_profiles |
$0.002 |
collector_place_reviews |
$0.001 |
collector_product_offers |
$0.002 |
collector_producthunt_posts |
$0.001 |
collector_pypi_packages |
$0.0003 |
collector_reddit_comments |
$0.002 |
collector_reddit_posts |
$0.0005 |
collector_redfin_search |
$0.0008 |
collector_rottentomatoes_movies |
$0.001 |
collector_search_images |
$0.0003 |
collector_search_videos |
$0.0004 |
collector_sec_filings |
$0.0005 |
collector_site_contacts |
$0.02 |
collector_site_documents |
$0.005 |
collector_stackoverflow |
$0.0003 |
collector_steam |
$0.0008 |
collector_subito_search |
$0.001 |
collector_target_product |
$0.0006 |
collector_tech_stack |
$0.005 |
collector_tiktok_profile |
$0.004 |
collector_tiktok_video |
$0.004 |
collector_tripadvisor_search |
$0.001 |
collector_trustpilot_reviews |
$0.06 |
collector_udemy_courses |
$0.001 |
collector_walmart_product |
$0.0015 |
collector_walmart_search |
$0.002 |
collector_wayback_machine |
$0.0003 |
collector_weather_forecast |
$0.0002 |
collector_web_search |
$0.0005 |
collector_wellfound_jobs |
$0.001 |
collector_whois_domain |
$0.005 |
collector_wikidata |
$0.0003 |
collector_wikipedia_articles |
$0.0005 |
collector_world_bank |
$0.0002 |
collector_yahoo_finance |
$0.001 |
collector_youtube_channel |
$0.0008 |
collector_youtube_search |
$0.0008 |
collector_youtube_video |
$0.005 |
collector_zalando_search |
$0.001 |
collector_zillow_property |
$0.005 |
collector_zillow_search |
$0.001 |
The same API is available as an MCP server for Claude, Cursor, ChatGPT and any MCP client. Product page: quanticdata.io/mcp-server/.
Remote server (OAuth 2.1, no key to paste): https://api.quanticdata.io/mcp
OAuth metadata: authorization server · protected resource
Claude Code (remote, OAuth):
claude mcp add --transport http quanticdata https://api.quanticdata.io/mcp
Local server (npx, API key in the environment):
QUANTICDATA_API_KEY=qd_live_… npx -y quanticdata-mcp
Claude Code (local):
claude mcp add quanticdata -e QUANTICDATA_API_KEY=qd_live_… -- npx -y quanticdata-mcp
Clients without native remote MCP support can bridge through npx -y quanticdata-mcp-remote.
Trial limits for keyless use are published by GET /mcp/trial-config (see Account).
Tools exposed by the remote server (as of 2026-10-19) and the REST endpoint behind each one:
| MCP tool | Endpoint |
|---|---|
scrape |
POST /scraper/extract |
search |
POST /scraper/serp |
search_and_read |
POST /scraper/serp + POST /scraper/extract |
search_bulk |
POST /scraper/serp/bulk |
search_bulk_status |
GET /scraper/serp/bulk/{jobId} |
map |
POST /scraper/map |
crawl |
POST /scraper/crawl |
crawl_status |
GET /scraper/crawl/{jobId} |
batch |
POST /scraper/batch |
batch_status |
GET /scraper/batch/{jobId} |
unlock |
POST /scraper/unlock |
ai_visibility |
POST /scraper/ai-visibility |
seo_audit |
POST /scraper/seo-audit |
list_collectors |
GET /scraper/collectors |
run_collector |
POST /scraper/collectors/{slug}/run |
collector_run_status |
GET /scraper/collectors/runs/{runId} |
create_dataset |
POST /scraper/datasets |
dataset_status |
GET /scraper/datasets/{jobId} |
generate_parser |
POST /scraper/parser/generate |
list_parser_presets |
GET /scraper/parser/presets |
save_parser_preset |
POST /scraper/parser/presets |
heal_parser_preset |
POST /scraper/parser/presets/{id}/heal |
parser_preset_stats |
GET /scraper/parser/presets/{id}/stats |
list_proxies |
GET /public/proxies |
generate_proxies |
POST /public/proxies/generate |
proxy_locations |
`GET /public/generator/{residential-premium |
whitelist_ip |
POST /public/proxies/whitelist-ip |
report |
(MCP only: usage report of the session) |
Skills for AI agents
5 Agent Skills (SKILL.md, the open Agent Skills format) teach Claude Code, Claude.ai, Codex, Cursor, Gemini CLI and any agent that reads SKILL.md how to use this API and the MCP server: the agent loads the one it needs when the task calls for it. They are published at quanticdata.io/.well-known/agent-skills/index.json and installed in one command with the skills CLI:
npx skills add https://quanticdata.io
Source and Claude Code plugin: github.com/quantumproxies/quanticdata-skills (npx skills add quantumproxies/quanticdata-skills, or copy skills/<name> into ~/.claude/skills/).
use-data-api: Call the REST Data API: authentication, response envelope, async jobs, referencesuse-mcp-server: Connect any MCP client: hosted OAuth endpoint or local npm package, tool presetsscrape-to-markdown: One URL to clean Markdown or structured fields; batch, map and crawl for manygenerate-proxies: Proxy strings from your plans: geo-targeting, sticky sessions, IP whitelistsfind-business-leads: Business lists and datasets: Collectors, AI Places Finder, dataset builder
Scrape one URL
Price: extract $0.0015 per call + $3/GB, max $0.02 per call · extract_render $0.0025 per call + $4/GB, max $0.05 per call · ai_extract $0.005 per call, max $1.50 per call. extract when the TLS/fetch tier served the page, extract_render when the browser did; both carry a perGb meter and a capUsd ceiling (pricing.json → meters). ai_extract + LLM tokens × ai_token_markup when ai_prompt/ai_schema is used. The pre-check reserves the worst case (render price unless engine is pinned to tls/fetch without render). (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/scrape (same handler, primary host only)
Try it in the Playground · Markdown for this group
Fetches one page through the residential pool and returns it as Markdown, HTML or text. Starts on a TLS-fingerprint tier (fast, cheap) and, with engine: auto, escalates to a stealth headless browser only when the target blocks; render: true (or engine: render, screenshot, xhr, reveal_hidden) forces the browser. Binary documents (PDF, DOCX, XLSX, CSV) are converted to text. Optional structured extraction (extract CSS schema or a stored presetId) and AI extraction (ai_prompt/ai_schema) run on the same fetch. Pass html instead of url to convert markup you already have (no fetch, no proxy bandwidth). What it does not do: it does not solve interactive captchas, and mode: summary returns no page content (so it cannot be combined with AI extraction). Billed per successful page by the engine that served it, plus a per-GB bandwidth component with a per-call cap; AI extraction adds the ai_extract fee plus marked-up LLM tokens. A page flagged as blocked or a target status ≥ 400 is not charged.
Authorizations:
Request Body schema: application/jsonrequired
| url | string <= 2048 characters http/https URL to scrape. Required unless |
| html | string Markup to convert instead of fetching (max 5 MB). |
| format | string Default: "markdown" Enum: "markdown" "html" "text" "raw"
|
| formats | Array of strings <= 3 items Items Enum: "markdown" "html" "text" Extra formats returned together under |
| data_format | string Enum: "markdown" "screenshot" Compatibility alias: |
| engine | string Default: "auto" Enum: "auto" "tls" "fetch" "render"
|
| autoEscalate | boolean Allow/forbid the auto engine's escalation to the browser (ignored once the plan's render budget is spent). |
| tlsProfile | string <= 64 characters TLS fingerprint profile for the TLS tier (opaque to the API; see /scraper/unlock for the known names). |
| render | boolean Default: false Force the stealth headless browser (JS execution). Bills the render rate. |
| mobile | boolean Default: false Mobile viewport and user agent. |
| waitMs | number Extra wait after load before capture, render tier (clamped by the service, max 15000). |
| waitForSelector | string <= 512 characters Wait until this CSS selector appears (render tier). |
| scrollToBottom | boolean Default: false Auto-scroll to trigger lazy-loaded content (render tier). |
| actions | Array of objects (PageAction) <= 20 items |
boolean or string
| |
| xhr | boolean Record the page's XHR/fetch traffic under |
object Assertion that the page is the real one: | |
object (ExtractSchema) Examples: {"title":"h1","price":".price","image":{"selector":"img.hero","attr":"src"},"features":{"selector":"li.feature","all":true}} Structured-extraction schema: field name → CSS selector, or an object with | |
| presetId | string Run a stored parser preset instead of an inline |
| contentMode | string Default: "smart" Enum: "smart" "article" "full"
|
| content_modes | Array of strings <= 3 items Items Enum: "smart" "article" "full" Return several content modes at once under |
| fullPage | boolean Legacy: |
| mode | string Default: "full" Enum: "full" "summary"
|
| include_links | boolean Default: false Also return de-duplicated absolute links under |
boolean or string Mine the page's own hydration state (Next/Nuxt/JSON islands) into | |
object Caller CSS rules: | |
| reveal_hidden | boolean Render tier: open |
object Markdown shaping; every key also accepted flat (snake_case) at the top level, flat wins. | |
| frontmatter | boolean |
| links_mode | string Enum: "inline" "footnote" "strip" |
| toc | boolean |
| max_tokens | number [ 200 .. 2000000 ] |
| images_mode | string Enum: "inline" "alt" "strip" |
| query | string <= 512 characters |
| highlights | integer [ 1 .. 20 ] |
| chunk | object |
| summary_sections | boolean |
| ai_prompt | string Natural-language instruction: the LLM turns the page into structured JSON under |
| ai_schema | object JSON Schema the AI output must follow (deterministic shape). Either |
object or string (ForwardHeaders) | |
object <= 50 properties name → value cookies sent to the target. | |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
| state | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Requires |
| city | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Requires |
| rotation | string Default: "rotating" Enum: "rotating" "sticky" New exit IP per request, or keep one IP for the session. Any other value is treated as |
| sessionId | string <= 64 characters Sticky session id (generated if omitted). |
| sessionDuration | number Sticky session lifetime in minutes (clamped by the proxy layer, 3–1440, default 10). |
Responses
| X-RateLimit-Limit | integer Requests allowed in the current hourly window for this key. |
| X-RateLimit-Remaining | integer Requests left in the window. |
| X-RateLimit-Reset | string <date-time> ISO-8601 instant when the window resets. |
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Payload of a scrape. Optional fields appear only when requested ( |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "format": "markdown",
- "country": "us",
- "extract": {
- "title": "h1",
- "price": ".price"
}
}Response samples
- 200
- 400
- 401
- 402
- 403
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Extraction successful",
- "payload": {
- "status": 200,
- "contentType": "text/html; charset=utf-8",
- "format": "markdown",
- "title": "Pricing — Example",
- "metadata": {
- "description": "Simple, transparent pricing.",
- "language": "en"
}, - "content": "# Pricing\n\nStarter — $9/month …",
- "data": {
- "title": "Pricing",
- "price": "$9"
}, - "engine": "tls",
- "attempts": 1,
- "escalated": false,
- "bytes": 48213,
- "durationMs": 1240,
- "geo": {
- "country": "us",
- "state": null,
- "city": null,
- "rotation": "rotating"
}, - "usage": {
- "cost_usd": 0.0015,
- "free_usd": 0.0015,
- "paid_usd": 0
}
}, - "pagination": { }
}Structured search results
Price: serp $0.0009 per call · serp_render $0.002 per call. Google (except autocomplete/reviews): serp when search_metadata.path is http, serp_render otherwise; Bing/DuckDuckGo: always serp. The pre-check reserves serp_render for Google. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/serp (same handler, primary host only)
Try it in the Playground · Markdown for this group
One search on Google, Bing or DuckDuckGo through the residential pool, returned as JSON in the common SERP-API shape: organic results, ads, People Also Ask, related searches, knowledge panels, AI Overview and 17 Google verticals (search_type). Google renders by default so JS-only blocks are populated; pass render: false for the cheaper HTTP tier. Identical requests are served from a 24h cache for free (search_metadata.from_cache). It does not paginate on your behalf: request one page at a time and read pagination.available_pages/has_next, or use /scraper/serp/bulk. Billed per successful search by the tier that served it (search_metadata.path); blocked searches answer 429 and cost nothing; autocomplete and reviews always bill the request price.
Authorizations:
Request Body schema: application/jsonrequired
| query | string <= 2048 characters Search query. Required except for ID-addressed verticals: |
| engine | string Default: "google" Enum: "google" "bing" "duckduckgo" |
| search_type | string Default: "search" Enum: "search" "shopping" "images" "news" "places" "maps" "videos" "scholar" "jobs" "autocomplete" "place_details" "hotels" "flights" "events" "product" "lens" "reviews" "trends" Vertical. Alias |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Proxy exit and engine locale. Alias |
| lang | string <= 10 characters UI language, e.g. |
| num | number Results to request (clamped to 1–100 by the service; Google serves ~10 per page and merges pages — see |
| page | number Result page, 1-based. |
| start | number Result offset (alternative to |
| device | string Default: "desktop" Enum: "desktop" "mobile" "ios" "android" Device to search as. |
| render | boolean Google: renders by default; |
| browser | string Enum: "chrome" "firefox" "safari" Browser to search as: |
| safe | string Enum: "active" "off" SafeSearch. |
boolean or integer Disable auto-corrected results. | |
| location | string <= 256 characters Human-readable search location ("Milan, Italy"), encoded to uule server-side. For |
| uule | string <= 512 characters Encoded uule token OR raw |
| google_params | object <= 24 properties Escape hatch: extra Google URL params (keys ≤40 chars of letters, digits, |
| jobs | boolean Jobs box on the main SERP. Alias |
| place_id | string <= 128 characters
|
| data_id | string <= 128 characters
|
string or number
| |
| departure_id | string <= 64 characters
|
| arrival_id | string <= 64 characters |
| outbound_date | string <= 10 characters YYYY-MM-DD. |
| return_date | string <= 10 characters |
| check_in_date | string <= 10 characters
|
| check_out_date | string <= 10 characters |
| adults | number
|
| children_ages | Array of numbers <= 10 items |
| free_cancellation | boolean |
| accommodation_type | string Enum: "hotels" "vacation_rentals" |
| currency | string <= 8 characters
|
| gps_coordinates | string <= 64 characters
|
| image_url | string <= 2048 characters
|
| exact_matches | boolean
|
| sort_by | string Enum: "relevance" "newest" "highest_rating" "lowest_rating"
|
| filter | string <= 256 characters
|
| next_page_token | string <= 512 characters
|
| wait_for | string <= 512 characters Render tier: CSS selector to wait for before capture. |
| include_html | boolean Also return the page HTML under |
| product_ids | boolean
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Search result in the common SERP-API JSON shape (drop-in for most existing SERP clients). Vertical arrays are always present (empty when the vertical did not apply); the single-object verticals ( |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "query": "best coffee grinder",
- "engine": "google",
- "country": "us",
- "lang": "en",
- "num": 10
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "SERP successful",
- "payload": {
- "search_metadata": {
- "status": "Success",
- "engine": "google",
- "created_at": "2026-10-07T09:12:44.000Z",
- "total_time_taken": 2.8,
- "attempts": 1,
- "bytes": 212544,
- "path": "http"
}, - "search_parameters": {
- "engine": "google",
- "q": "best coffee grinder",
- "search_type": "search",
- "device": "desktop",
- "country": "us",
- "language": "en",
- "page": 1
}, - "organic": [
- {
- "rank": 1,
- "title": "The 6 Best Coffee Grinders of 2026",
- "display_link": "example.com › reviews",
- "source": "example.com",
- "description": "We tested 24 burr grinders…",
- "date": "12 Sep 2026"
}
], - "ads": [ ],
- "people_also_ask": [
- {
- "question": "Is a burr grinder worth it?"
}
], - "related_searches": [
- {
- "query": "best coffee grinder under 100"
}
], - "ai_overview": null,
- "knowledge_graph": null,
- "pagination": {
- "current": 1,
- "next": 2,
- "total_pages": null,
- "available_pages": [
- 1,
- 2,
- 3,
- 4,
- 5
], - "has_next": true
}, - "usage": {
- "cost_usd": 0.0009,
- "free_usd": 0.0009,
- "paid_usd": 0
}
}, - "pagination": {
- "current": 1,
- "next": 2,
- "total_pages": null,
- "available_pages": [
- 1,
- 2,
- 3,
- 4,
- 5
], - "has_next": true
}
}Start a multi-page search job
Price: serp_render $0.002 per call · serp $0.0009 per call. Google: serp_render × max_pages up front; Bing/DuckDuckGo: serp × max_pages. Unfetched pages refunded at settlement. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/serp/bulk (same handler, primary host only)
Try it in the Playground · Markdown for this group
Paginates one query across up to 10 result pages asynchronously, riding real pagination on one session. Returns a job id immediately; poll GET /scraper/serp/bulk/{jobId} for the merged, de-duplicated organic results as pages land, or pass a webhook to receive the finished job. Only web-type verticals (search, news, videos, images, shopping) are supported here. Charged up front for max_pages; pages the query does not have are refunded when the job settles.
Authorizations:
Request Body schema: application/jsonrequired
| query required | string <= 2048 characters |
| engine | string Default: "google" Enum: "google" "bing" "duckduckgo" |
| search_type | string Default: "search" Enum: "search" "news" "videos" "images" "shopping" Alias |
| max_pages | integer [ 1 .. 10 ] Default: 5 |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Alias |
| lang | string <= 10 characters Alias |
| device | string Enum: "desktop" "mobile" "ios" "android" Device to search as. |
| render | boolean |
| wait_for | string <= 512 characters |
| browser | string Enum: "chrome" "firefox" "safari" Browser to search as: |
| safe | string Enum: "active" "off" |
boolean or integer | |
| uule | string <= 512 characters |
| location | string <= 256 characters |
| google_params | object <= 24 properties |
| webhook | string <= 2048 characters Public http(s) URL that receives the finished job by POST. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Answer of a POST that started an async job. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "query": "best coffee grinder",
- "engine": "google",
- "country": "us",
- "max_pages": 3
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Bulk SERP started",
- "payload": {
- "id": "sb_4d1e9c",
- "status": "running",
- "query": "best coffee grinder",
- "total": 3,
- "completed": 0,
- "statusUrl": "/api/v1/scraper/serp/bulk/sb_4d1e9c",
- "usage": {
- "cost_usd": 0.006,
- "free_usd": 0.006,
- "paid_usd": 0
}
}, - "pagination": { }
}Poll a multi-page search job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: GET https://api.quanticdata.io/v1/serp/bulk/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Progress and merged organic results of a bulk search job you own. Pass the previous response's nextCursor as since to receive only new rows. Jobs are kept about an hour after they finish. Free to poll.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
query Parameters
| since | integer Organic cursor from the previous poll's |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/serp/bulk/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Bulk SERP status",
- "payload": {
- "id": "sb_4d1e9c",
- "status": "completed",
- "query": "best coffee grinder",
- "total": 3,
- "completed": 3,
- "failed": 0,
- "pages": [
- {
- "page": 1,
- "organic_count": 10,
- "bytes": 210331,
- "path": "http"
}, - {
- "page": 2,
- "organic_count": 10,
- "bytes": 198002,
- "path": "http"
}, - {
- "page": 3,
- "organic_count": 9,
- "bytes": 190114,
- "path": "http"
}
], - "organic": [
- {
- "rank": 1,
- "title": "The 6 Best Coffee Grinders of 2026",
- "display_link": "example.com",
- "description": "…"
}
], - "related_searches": [ ],
- "ai_overview": null,
- "nextCursor": 29,
- "createdAt": 1759828364000,
- "finishedAt": 1759828391000
}, - "pagination": { }
}Cancel a multi-page search job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: DELETE https://api.quanticdata.io/v1/serp/bulk/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Stops a running bulk search job you own. Pages never fetched are refunded at settlement.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/serp/bulk/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Bulk SERP cancelled",
- "payload": {
- "id": "sb_4d1e9c",
- "status": "cancelled"
}, - "pagination": { }
}Discover a site's URLs
Price: map $0.003 per call (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/map (same handler, primary host only)
Try it in the Playground · Markdown for this group
Merges robots.txt sitemaps, /sitemap.xml (nested indexes included) and same-domain homepage links into one de-duplicated list, synchronously. Returns up to limit URLs plus the site-wide total and a per-section summary; group_by: path returns the path tree instead of the list. It does not fetch page bodies — pair it with /scraper/batch for that. One flat price per call.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters Seed URL. |
| limit | number Default: 100 Max URLs to return (service cap 5000). |
| search | string <= 256 characters Only return URLs containing this substring. |
| includeSubdomains | boolean Default: false |
| sitemapOnly | boolean Default: false Skip the homepage link scrape. |
| group_by | string Value: "path" Return the path tree with counts instead of the URL list. Alias |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "limit": 100,
- "search": "blog"
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Map successful",
- "payload": {
- "count": 100,
- "total": 2417,
- "summary": {
- "/blog": 1988,
- "/docs": 240,
- "/": 1
}, - "sources": {
- "sitemap": 2410,
- "homepage": 42
}, - "durationMs": 3120,
- "geo": {
- "country": null
}, - "usage": {
- "cost_usd": 0.003,
- "free_usd": 0.003,
- "paid_usd": 0
}
}, - "pagination": { }
}Start a site crawl
Price: crawl_page $0.0003 per call · extract_render $0.0025 per call + $4/GB, max $0.05 per call. crawl_page × min(limit, 500) up front, or extract_render × pages when render is true. Refund of the unfetched share at settlement. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/crawl (same handler, primary host only)
Try it in the Playground · Markdown for this group
Breadth-first crawl from a seed URL through the residential pool, each page converted to the requested format. Returns a job id immediately; poll GET /scraper/crawl/{jobId}. Charged up front on limit pages (render price per page with render: true); unfetched or failed pages are refunded when the job settles. A render crawl takes one browser-render token at submission and its pages then queue on the plan's render concurrency.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters Seed URL. |
| limit | number Default: 50 Max pages (cap 500). Billed on this up front. |
| depth | number Default: 3 Max link depth from the seed (cap 10). |
| format | string Default: "markdown" Enum: "markdown" "html" "text" |
| contentMode | string Default: "smart" Enum: "smart" "article" "full" Alias |
| render | boolean Default: false Render every page with the stealth browser (slower, rendered rate). |
| sameDomain | boolean Default: true |
| allowSubdomains | boolean Default: false |
| include | Array of strings <= 50 items [ items <= 256 characters ] URL substrings/globs to include, e.g. ["/guides/*"]. |
| exclude | Array of strings <= 50 items [ items <= 256 characters ] |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Answer of a POST that started an async job. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "limit": 50,
- "depth": 3,
- "include": [
- "/guides/*"
]
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Crawl started",
- "payload": {
- "id": "cr_d5b8a1",
- "status": "running",
- "limit": 50,
- "depth": 3,
- "format": "markdown",
- "pagesCrawled": 0,
- "pagesQueued": 1,
- "statusUrl": "/api/v1/scraper/crawl/cr_d5b8a1",
- "usage": {
- "cost_usd": 0.015,
- "free_usd": 0.015,
- "paid_usd": 0
}
}, - "pagination": { }
}Poll a crawl job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: GET https://api.quanticdata.io/v1/crawl/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Progress and crawled pages of a job you own. Use since (the previous nextCursor) to page a large crawl and include_content=false for cheap status checks. Jobs are kept about an hour after they finish. Free to poll.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
query Parameters
| since | integer Page cursor from the previous poll's |
| include_content | string Enum: "true" "false" Omit to get the full job; |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/crawl/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Crawl status",
- "payload": {
- "id": "cr_d5b8a1",
- "status": "completed",
- "limit": 50,
- "depth": 3,
- "format": "markdown",
- "pagesCrawled": 37,
- "pagesQueued": 0,
- "pages": [
- {
- "status": 200,
- "title": "Getting started",
- "depth": 1,
- "content": "# Getting started\n…"
}
], - "nextCursor": 37,
- "hasMore": false,
- "createdAt": 1759828364000,
- "finishedAt": 1759828512000
}, - "pagination": { }
}Cancel a crawl job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: DELETE https://api.quanticdata.io/v1/crawl/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Stops a running crawl you own; pages never fetched are refunded at settlement.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/crawl/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Crawl cancelled",
- "payload": {
- "id": "cr_d5b8a1",
- "status": "cancelled"
}, - "pagination": { }
}Scrape many URLs asynchronously
Price: batch_url $0.0004 per call · extract_render $0.0025 per call + $4/GB, max $0.05 per call. batch_url × urls up front (or extract_render × urls when rendering). Failed URLs refunded at settlement. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/batch (same handler, primary host only)
Try it in the Playground · Markdown for this group
Up to 5,000 URLs you already know, with shared options, run concurrently through the residential pool. Returns a job id immediately; poll GET /scraper/batch/{jobId} or pass a webhook to receive the finished job by POST. Charged up front per URL (render price with render: true or engine: render); the failed/blocked share is refunded when the job settles. A render batch takes one browser-render token at submission.
Authorizations:
Request Body schema: application/jsonrequired
| urls required | Array of strings [ 1 .. 5000 ] items [ items <= 2048 characters ] |
| format | string Default: "markdown" Enum: "markdown" "html" "text" |
| engine | string Default: "auto" Enum: "auto" "tls" "fetch" "render" |
| render | boolean Default: false Force the headless browser for every URL. |
object (ExtractSchema) Examples: {"title":"h1","price":".price","image":{"selector":"img.hero","attr":"src"},"features":{"selector":"li.feature","all":true}} Structured-extraction schema: field name → CSS selector, or an object with | |
| contentMode | string Default: "smart" Enum: "smart" "article" "full" Alias |
| fullPage | boolean Legacy: contentMode full. |
| mode | string Default: "full" Enum: "full" "summary"
|
| concurrency | number [ 1 .. 20 ] Default: 5 Simultaneous fetches (clamped 1–20; your tier's batch concurrency also applies). |
| webhook | string <= 2048 characters Public http(s) URL that receives the finished job by POST. |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Answer of a POST that started an async job. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "format": "markdown",
- "mode": "summary"
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Batch started",
- "payload": {
- "id": "bt_91ac07",
- "status": "running",
- "total": 2,
- "completed": 0,
- "failed": 0,
- "statusUrl": "/api/v1/scraper/batch/bt_91ac07",
- "usage": {
- "cost_usd": 0.0004,
- "free_usd": 0.0004,
- "paid_usd": 0
}
}, - "pagination": { }
}Poll a batch job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: GET https://api.quanticdata.io/v1/batch/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Progress and per-URL results of a job you own. Polls return metadata only unless include_content=true; pass the previous nextCursor as since to receive only newer items. Jobs are kept about an hour after they finish. Free to poll.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
query Parameters
| since | integer Item cursor from the previous poll's |
| include_content | string Enum: "true" "false"
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/batch/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Batch status",
- "payload": {
- "id": "bt_91ac07",
- "status": "completed",
- "total": 2,
- "completed": 2,
- "failed": 0,
- "contentTruncated": false,
- "items": [
- {
- "status": 200,
- "title": "Page A",
- "description": "…",
- "contentLength": 5120,
- "engine": "tls",
- "bytes": 31870
}, - {
- "status": 200,
- "title": "Page B",
- "description": null,
- "canonical": null,
- "contentLength": 2210,
- "engine": "tls",
- "bytes": 12003
}
], - "nextCursor": 2,
- "hasMore": false,
- "createdAt": 1759828364000,
- "finishedAt": 1759828370000
}, - "pagination": { }
}Cancel a batch job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: DELETE https://api.quanticdata.io/v1/batch/{jobId} (same handler, primary host only)
Try it in the Playground · Markdown for this group
Stops a running batch you own; URLs never fetched are refunded at settlement.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/batch/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Batch cancelled",
- "payload": {
- "id": "bt_91ac07",
- "status": "cancelled"
}, - "pagination": { }
}A YouTube video as text and pictures for a model: the transcript in the spoken language with timestamps, the author's chapters and small storyboard frames placed at the moments that matter, in one timeline.
Read a YouTube video for a model
Price: video $0.02 per call. video per successful read, whatever the length; a window (start/end) or a transcript-only read (max_frames: 0) costs the same. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
One YouTube URL in; out come the metadata, the transcript in the language that is spoken with [m:ss] timestamps (never a translated track: a translation adds the translator's errors on top of the captioner's, and the reading model translates better from the original), the chapters the author wrote, and small storyboard frames picked where the words point at the screen ("as you can see", "come vedete"), where a price is said, at each chapter start and every so often in between, so no stretch goes unseen. content interleaves all of it in one Markdown timeline the model reads in order; the frames are base64 JPEGs you attach to the prompt next to their [frame N] marker. No model runs on our side. Use start/end to read a part of a long video and max_tokens to bound the text; max_frames: 0 returns the transcript alone. Reads that the platform refuses from a datacenter address are retried through a residential exit automatically. Pay per success: a video that cannot be read (removed, private, sign-in gated, live not started) answers a stable payload.code and is never billed. The MCP server exposes the same call as the read_video tool.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters YouTube URL: watch, youtu.be, shorts, embed or live. |
| languages | Array of strings <= 5 items [ items [ 2 .. 12 ] characters ] Caption languages to prefer, e.g. |
| max_frames | integer [ 0 .. 30 ] Default: 12 Frames to include; 0 = transcript only. |
| frames | boolean Default: true false = the frame list without image data (positions, reasons and quotes only). |
number or string Read from this point: seconds or | |
number or string Read up to this point: seconds or | |
| max_tokens | integer [ 200 .. 100000 ] Budget for |
| segments | boolean Default: false true = also return the raw timed cues under |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object What a model needs to understand a video without watching it. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "max_frames": 6,
- "max_tokens": 4000
}Response samples
- 200
- 400
- 401
- 402
- 403
- 404
- 422
- 429
- 502
- 503
- 504
{- "type": "response",
- "message": "Video read successful",
- "payload": {
- "video": {
- "platform": "youtube",
- "id": "aircAruvnKk",
- "title": "But what is a neural network? | Deep learning chapter 1",
- "channel": "3Blue1Brown",
- "channel_id": "UCYO_jab_esuFRV4b17AJtAw",
- "duration_seconds": 1120,
- "view_count": 24894419,
- "keywords": [
- "neural network",
- "deep learning"
], - "is_live": false,
}, - "transcript": {
- "source": "captions",
- "language": "en",
- "available": [
- {
- "code": "en",
- "kind": "manual"
}, - {
- "code": "it",
- "kind": "manual"
}
]
}, - "chapters": [
- {
- "start": 0,
- "title": "Introduction example"
}, - {
- "start": 67,
- "title": "Series preview"
}, - {
- "start": 162,
- "title": "What are neurons?"
}
], - "frames": [
- {
- "n": 1,
- "t": 130,
- "at": "2:10",
- "reason": "cue",
- "quote": "and in recent years there's been sort of a boom in research towards these variants",
- "width": 160,
- "height": 90,
- "mime": "image/jpeg",
- "data": "/9j/4AAQSkZJRgABAQAAAQABAAD…"
}, - {
- "n": 2,
- "t": 165,
- "at": "2:45",
- "reason": "chapter",
- "quote": "What are neurons?",
- "width": 160,
- "height": 90,
- "mime": "image/jpeg",
- "data": "/9j/4AAQSkZJRgABAQAAAQABAAD…"
}
], - "frame_size": {
- "width": 160,
- "height": 90,
- "interval": 10
}, - "format": "markdown",
- "content": "# But what is a neural network? | Deep learning chapter 1\nChannel: 3Blue1Brown · Duration: 18:40 · Views: 24894419\nURL: https://www.youtube.com/watch?v=aircAruvnKk\nTranscript: en (captions), original language, timestamps [m:ss]\nFrames: 6 storyboard frames of 160×90 px, marked [frame N · m:ss · why]; low resolution — scenes and objects are visible, small text is not\n\n## Description\nWhat are the neurons, why are there layers, and what is the math underlying it?\n…\n\n## Timeline\n## [0:00] Introduction example\n\n[0:04] This is a 3. It's sloppily written and rendered at an extremely low resolution of 28x28 pixels, but your brain has no trouble recognizing it as a 3. …\n[frame 1 · 2:10 · the speaker points at the screen]\n[2:12] but in these two introductory videos you and I are just going to look at the simplest plain vanilla form …\n\n## [2:42] What are neurons?\n\n[frame 2 · 2:45 · chapter start]\n[2:42] So let's start by looking at an example of a neuron …",
- "tokens": {
- "estimated": 3996,
- "full": 5780,
- "truncated": true,
- "estimator": "chars/4 heuristic"
}, - "notes": [
- "content trimmed to max_tokens: pass start/end to read the rest of the video"
], - "meta": {
- "bytes": 502969,
- "via_proxy": false
}
}, - "pagination": { }
}Replay any HTTP request through a residential exit with a real browser fingerprint; prepaid per GB.
The same engine answers in two ways: the REST call below (POST /scraper/unlock, API key, JSON in and out) and a forward proxy you point an existing HTTP client or scraper at. Both spend the same prepaid Web Unlocker GB, one balance per tier (premium = residential exits, mobile = mobile exits). The GB are bought on the Web Unlocker tab of the plans page, paid from the wallet balance, and are separate from the Data API free credit.
Use the REST call when you can change the code that sends the request. Use the forward proxy when the code already speaks to a proxy (host, port, user, password) and should keep working unchanged.
| Host | unlock.quanticdata.io |
| Port | 9000 (HTTP proxy) |
| Authentication | Proxy-Authorization: Basic with a proxy user: username unlock-<12 hex>, 32-character password. Your API key is not accepted by the proxy. |
| Targets | http:// and https:// URLs. HTTP/1.1 inside a CONNECT tunnel. |
| Limits | Request body up to 8 MB. Text responses up to 5 MB, binary up to 25 MB. At most 8 redirects are followed. |
Proxy users
Create, rotate and delete proxy users on the Web Unlocker page of the dashboard, up to 20 per account. The password is shown when the user is created or rotated. The proxy caches a successful login for 60 seconds, so a rotated or deleted password can keep working for up to a minute. The same page builds ready-made proxy strings with the targeting below.
Three ways to send a request
1. HTTPS target through CONNECT — the normal proxy setting of any client. The proxy re-issues your request itself, so it terminates TLS with its own certificate: trust the interception CA (GET /scraper/unlock/ca) or turn verification off (curl -k, verify=False).
curl -x http://unlock.quanticdata.io:9000 -U 'unlock-xxxxxxxxxxxx:PROXY_PASSWORD' \
--cacert qp-unlocker-ca.pem 'https://example.com/'
import requests
proxy = "http://unlock-xxxxxxxxxxxx-country-us:PROXY_PASSWORD@unlock.quanticdata.io:9000"
r = requests.get("https://example.com/", proxies={"http": proxy, "https": proxy}, verify="qp-unlocker-ca.pem")
print(r.status_code, r.headers.get("x-qp-unlocker-attempts"))
2. Direct mode, no certificate — send the target in x-qp-url and address the proxy itself with plain HTTP. The proxy makes the TLS connection to the site, so nothing has to be installed. The method and body of your call are forwarded; x-qp-method overrides the method.
curl -x http://unlock.quanticdata.io:9000 -U 'unlock-xxxxxxxxxxxx:PROXY_PASSWORD' \
-H 'x-qp-url: https://example.com/api/search' \
-H 'content-type: application/json' -d '{"q":"shoes"}' http://unlock/
3. Plain-HTTP target — an absolute-URI request (GET http://example.com/ HTTP/1.1), what any client sends for an http:// URL through a proxy. No certificate involved.
Targeting in the username
Append options to the proxy user, each as -name-value: unlock-xxxxxxxxxxxx-country-us-session-abc123-ttl-30. Unknown options are ignored.
| Option | Values | Effect |
|---|---|---|
country-xx |
2-letter country code | Exit country. Without it: the country of a 2-letter domain ending (.de, .fr), otherwise US. |
state-<slug>, city-<slug> |
letters, digits, _ (up to 32) |
Exit region and city, e.g. -state-new_york-city-new_york. |
session-<id> (or sid-<id>) |
letters and digits (up to 32) | Keeps the same exit IP across requests and connections. |
ttl-<minutes> |
3 to 1440 | How long that session's exit is kept; only together with session. |
profile-<name> |
chrome (default), firefox, safari, safari_ios, edge, brave, mobile |
Browser fingerprint. Other values fall back to the default. |
mobile |
— | Mobile browser fingerprint on the same exits. It does not switch to the mobile network. |
tier-<name> |
premium (default), mobile |
Product: exit network and GB balance the request is billed on. |
policy-<name> |
browser (default), passthrough |
passthrough sends your own identity headers instead of the fingerprint's. |
Control headers
Optional request headers, read by the proxy and removed before the request reaches the site (any other header, including other x-qp-* names, is forwarded). They work on every way of sending a request, inside a CONNECT tunnel too. True values: 1, true, yes, on; false: 0, false, no, off, none or empty. An invalid value is ignored and reported in x-qp-warning. The header names used by other unlocker services for the same options are accepted as aliases, so existing code keeps working.
| Header | Values | Effect |
|---|---|---|
x-qp-url |
absolute http(s) URL |
Target in direct mode; wins over the request line. |
x-qp-method |
HTTP verb | Method sent to the site. |
x-qp-country (or x-qp-geo) |
2-letter code | Exit country for this request. |
x-qp-session (or x-qp-session-id) |
letters and digits (up to 32) | Exit session for this request. |
x-qp-rotation |
sticky, rotating |
Session behaviour. |
x-qp-profile (or x-qp-tls-profile) |
profile name | Browser fingerprint. |
x-qp-keep-headers |
true/false | Send your own identity headers verbatim. |
x-qp-render |
html or true, png, false |
Run the page in a headless browser (GET/HEAD); false turns the browser off, escalation included. |
x-qp-auto-render (or x-qp-escalate) |
true/false | Browser escalation of a blocked GET (on by default). |
x-qp-success-status |
comma-separated codes, 100 to 599 | Origin statuses relayed as success, never retried. |
x-qp-timeout |
milliseconds | Per-attempt timeout at the site. |
x-qp-wait-for (or x-qp-wait-for-selector) |
CSS selector (up to 256) | Browser waits for this element before capturing. |
x-qp-wait-ms (or x-qp-wait) |
0 to 15000 | Extra settle time in the browser. |
x-qp-return-cookies |
true | Return the site's cookie jar in x-qp-cookies. |
Response headers
The site's status, headers and body are relayed (the body decompressed, Set-Cookie lines from every redirect kept), plus:
| Header | Meaning |
|---|---|
x-qp-request-id |
Id of this exchange, to quote to support. |
x-qp-unlocker-attempts |
Attempts across every tier. |
x-qp-unlocker-profile |
Fingerprint that served the response. |
x-qp-session |
Exit session used. |
x-qp-country |
Exit country used. |
x-qp-final-url |
URL after redirects. |
x-qp-unlocker-rendered, x-qp-unlocker-escalated |
1 when the headless browser served it, or was reached by escalation. |
x-qp-clearance |
hit, miss, minted, stale or off. |
x-qp-unlocker-blocked |
Block reason, when every attempt came back blocked. |
x-qp-block-class |
js_challenge, captcha, access_denied, rate_limited, fingerprint, geo, timeout or unknown. |
x-qp-vendor |
Anti-bot vendor, when recognised. |
x-qp-hint |
Suggestion when blocked, e.g. try the mobile tier. |
x-qp-origin-status |
The site's real status, when the proxy changed it (a block page that came back as 2xx/3xx is relayed as 502). |
x-qp-cookies |
URL-encoded JSON cookie jar, with x-qp-return-cookies. |
x-qp-ratelimit-limit, x-qp-ratelimit-remaining |
Requests per minute and what is left. |
x-qp-warning |
A control header or option that was ignored, and why. |
Retries and sessions
GET, HEAD and OPTIONS are retried up to three times on a new exit with a different fingerprint, then escalated to a headless browser that can start in parallel. Any other method gets exactly one attempt and no browser fallback: a response means the site saw the request, and replaying a POST could submit it twice. With a session in the username the exit cannot change, so there is one normal attempt; the browser fallback still runs.
Errors from the proxy itself
Errors generated by the proxy (not relayed from the site) are JSON, {"error":{"code":"…","message":"…"}}, with the code repeated in the x-qp-unlocker header. A CONNECT that is refused gets no body: the status line plus X-Qp-Unlocker (code) and, for 402, X-Qp-Unlocker-Message (curl prints "Received HTTP code 402 from proxy after CONNECT").
| Status | Code | When |
|---|---|---|
| 400 | bad_target, not_a_proxy_request |
Malformed or non-absolute target URL, credentials in the URL, or a request that is neither proxy-shaped nor direct mode. |
| 402 | no_credit |
The tier has no usable GB: never bought, used up or expired. The message says which and links the plans page. After buying, a cached 402 can last up to 30 seconds. |
| 403 | target_forbidden, target_denied |
Private or internal address, or a destination that is not reachable through the unlocker (banking, payments, login providers, crypto sites). |
| 407 | proxy_auth_required, proxy_auth_invalid |
Missing or wrong proxy user, or a suspended account. Comes with Proxy-Authenticate: Basic. |
| 413 | body_too_large |
Request body over 8 MB. |
| 429 | rate_limited, too_many_connections, sensitive_rate_limited, auth_rate_limited |
Requests per minute, concurrent connections, non-GET requests to login-like paths, or more than 30 failed logins per minute from one IP. retry-after says when to retry. Not billed. |
| 502, 504 | upstream_failed, render_failed |
The site could not be reached in time, or the browser render failed. |
| 503 | no_exit_pool |
The tier has no exit network for this account (e.g. tier-mobile without mobile GB). |
Billing and limits
Every byte the exit network carries for your request is debited from the tier's GB: retries, blocked pages, failed attempts and the browser's page load included (request bodies and response bodies; headers are not counted). 1 GB = 10^9 bytes. 429 responses and failed logins are not billed. The balance is checked when the proxy logs you in, so a session can run for up to a minute past the end of the GB. Requests per minute and concurrent connections follow the account's Data API tier (see Rate limits and tiers).
Replay a request through the Web Unlocker
Price: unlock_request $2.40/GB of transferred data. Flat base is 0; the whole charge is the unlock_request perGb meter applied to usage.bytes, debited from the prepaid unlocker GB of the chosen tier. No wallet charge, no free tier. 402 when the tier has no usable GB (never bought, used up or expired). (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Send a request the way your own HTTP client would (url, method, headers, body) and get it back replayed through a residential (or mobile) exit under a real browser TLS fingerprint. GET/HEAD/OPTIONS retry on a fresh exit IP under a different fingerprint when blocked and finally escalate to a headless browser that answers JavaScript challenges; any other method gets exactly one attempt (a response means the target saw it, and replaying a POST could double-submit). A still-blocked page is returned with blocked: true, blockClass and vendor, never as a silent success; failOnBlock: true turns that into a 502. It does not solve interactive captchas. This is the same engine as the forward proxy (documented at the top of this section), without the proxy protocol — no certificate to install. Billing is different from every other Data API call: it is metered in bytes against the tier's prepaid Web Unlocker GB (premium = residential exits, mobile = mobile exits), not the wallet, and every attempt counts — retries, a blocked page, the browser escalation's page load.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters |
| method | string^[A-Za-z]{1,16}$ Default: "GET" |
object or string (ForwardHeaders) | |
| body | string Request body as UTF-8 text (JSON, form data…). Use this OR |
| bodyBase64 | string Request body as base64 for binary payloads. Max 8 MB decoded. |
| tier | string Default: "premium" Enum: "premium" "mobile" Which prepaid pool pays and which exits are used. Anything other than |
| tlsProfile | string Default: "chrome" Enum: "chrome" "firefox" "safari" "safari_ios" "edge" "brave" "mobile" |
| mobile | boolean Default: false Mobile Safari fingerprint (fingerprint only — the product tier is |
string or boolean
| |
| autoRender | boolean Default: true Escalate a blocked GET to the browser. |
| keepHeaders | boolean Default: false |
| successStatusCodes | Array of integers <= 20 items [ items [ 100 .. 599 ] ] Origin statuses to accept as success — never treated as a block, never retried. |
| timeoutMs | integer [ 1000 .. 120000 ] Per-attempt timeout at the target (capped by the service's 90 s total budget). |
| failOnBlock | boolean Default: false 502 instead of a 200 with |
| waitForSelector | string [ 1 .. 256 ] characters Browser tier: CSS selector to wait for before capture. |
| waitMs | integer [ 0 .. 15000 ] |
| returnCookies | boolean Default: false Return the origin's cookie jar under |
object <= 50 properties Cookies merged into the Cookie header sent to the target (e.g. a clearance obtained earlier). | |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
| state | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Requires |
| city | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Requires |
| rotation | string Default: "rotating" Enum: "rotating" "sticky" |
| sessionId | string <= 64 characters Sticky session id — reuse it across calls to keep one exit IP. |
| sessionDuration | number Sticky session lifetime in minutes. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object The target's response, replayed. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "method": "GET",
- "headers": {
- "Accept": "application/json"
}, - "country": "us",
- "tier": "premium"
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 502
- 503
{- "type": "response",
- "message": "Unlocker request successful",
- "payload": {
- "status": 200,
- "headers": {
- "content-type": "application/json; charset=utf-8",
- "cache-control": "no-store"
}, - "body": "{\"results\":[{\"id\":1,\"name\":\"Runner\"}]}",
- "bodyBase64": "eyJyZXN1bHRzIjpbeyJpZCI6MSwibmFtZSI6IlJ1bm5lciJ9XX0=",
- "contentType": "application/json; charset=utf-8",
- "profile": "chrome",
- "attempts": 1,
- "blocked": false,
- "clearance": "miss",
- "exitSessionId": "s_2f91",
- "strategy": {
- "startTier": "tls",
- "hedged": false
}, - "rendered": false,
- "escalated": false,
- "tier": "premium",
- "geo": {
- "country": "us",
- "state": null,
- "city": null,
- "rotation": "rotating"
}, - "usage": {
- "bytes": 18432,
- "unlock_gb_remaining": 4.98,
- "unlock_gb_purchased": 5
}
}, - "pagination": { }
}Download the unlocker CA certificate
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The interception CA used by the Web Unlocker forward proxy (CONNECT mode). The proxy terminates your TLS to read and rewrite the request, so an HTTP client that keeps certificate verification on must trust this file for the target host (curl --proxy-cacert qp-unlocker-ca.pem --cacert qp-unlocker-ca.pem …). Not needed for POST /scraper/unlock, nor for the proxy's direct mode. Public by nature, kept behind the key so downloads are attributable. Free.
Authorizations:
Responses
Response Schema: application/x-pem-file
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/unlock/ca' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 503
-----BEGIN CERTIFICATE----- MIIB… -----END CERTIFICATE-----
Natural-language scraping agent
Price: ai_extract $0.005 per call, max $1.50 per call · extract $0.0015 per call + $3/GB, max $0.02 per call · serp $0.0009 per call · map $0.003 per call. ai_extract + steps × extract + searches × serp + mapped × map + tokens × ai_token_markup, capped at meters.ai_extract.capUsd. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Describe a task in plain English; a model drives the scraper API as a tool — formats the request, fetches the page(s) through residential proxies, can search and map when the task needs it, and returns the extracted JSON under data with the pages it visited under steps. Use it when you do not want to write selectors or a schema; use /scraper/extract with extract/ai_schema when you already know the page. Not deterministic and not the cheapest path for repeated layouts (see /scraper/parser/generate). Billed as the ai_extract base fee plus one extract per page fetched, serp per search, map per map, plus LLM tokens × ai_token_markup, capped at the ai_extract meter's capUsd; the pre-check reserves that cap.
Authorizations:
Request Body schema: application/jsonrequired
| task required | string Plain-English instruction, e.g. "get every product with its name and price from this page". |
| url | string Starting URL, if the task does not already contain one. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "task": "Get every plan and its monthly price",
}Response samples
- 200
- 400
- 401
- 402
- 429
- 500
- 503
{- "type": "response",
- "message": "AI extraction successful",
- "payload": {
- "data": {
- "plans": [
- {
- "name": "Starter",
- "price_usd": 9
}, - {
- "name": "Growth",
- "price_usd": 29
}
]
}, - "searches": 0,
- "mapped": 0,
- "model": "gpt-4o-mini",
- "bytes": 48213,
- "usage": {
- "input_tokens": 3120,
- "output_tokens": 180,
- "cost_usd": 0.0019,
- "free_usd": 0.0019,
- "paid_usd": 0
}
}, - "pagination": { }
}AI Places Finder
Price: places_ai $0.005 per call, max $3 per call · serp_render $0.002 per call. places_ai + searches × serp_render + tokens × ai_token_markup, capped at meters.places_ai.capUsd. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Describe what you are looking for ("find every car repair shop in Naples"); the model crafts the Google local queries, paginates, de-duplicates and returns the aggregated businesses, optionally enriched from each knowledge panel (phone, website, hours, full address). For a deterministic, per-row-priced alternative use the google_maps_places collector. Billed as the places_ai base plus serp_render per search run plus LLM tokens × ai_token_markup, capped at the places_ai meter's capUsd; the pre-check reserves that cap.
Authorizations:
Request Body schema: application/jsonrequired
| task required | string |
| country | string ISO country override for the proxy exit and |
| enrich | boolean Default: true Fill phone/website/hours/address from each business's knowledge panel. |
| max_enrich | number Default: 15 Knowledge-panel lookups budget (cap 30). |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Shared shape of the AI Places and AI Shopping finders. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "task": "find every car repair shop in Naples",
- "country": "it",
- "max_enrich": 10
}Response samples
- 200
- 400
- 401
- 402
- 429
- 500
- 503
{- "type": "response",
- "message": "Places search successful",
- "payload": {
- "places": [
- {
- "name": "Autofficina Esposito",
- "rating": 4.6,
- "reviews": 212,
- "address": "Via Toledo 12, 80134 Napoli NA",
- "phone": "+39 081 000 0000",
}
], - "total": 38,
- "enriched": 10,
- "queries": [
- "autofficina Napoli",
- "meccanico Napoli"
], - "summary": "38 repair shops across central Naples.",
- "model": "gpt-4o-mini",
- "usage": {
- "input_tokens": 9800,
- "output_tokens": 2200,
- "cost_usd": 0.0218,
- "free_usd": 0.0218,
- "paid_usd": 0
}
}, - "pagination": { }
}AI Shopping Finder
Price: shopping_ai $0.005 per call, max $3 per call · serp_render $0.002 per call. shopping_ai + searches × serp_render + tokens × ai_token_markup, capped at meters.shopping_ai.capUsd. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Describe the product ("find the cheapest Nintendo Switch OLED in Italy"); the model crafts Google Shopping queries, paginates, de-duplicates and returns the aggregated products with merchant and price. For a deterministic alternative use /scraper/serp with search_type: shopping or the google_shopping collector. Billed as the shopping_ai base plus serp_render per search plus LLM tokens × ai_token_markup, capped at the shopping_ai meter's capUsd; the pre-check reserves that cap.
Authorizations:
Request Body schema: application/jsonrequired
| task required | string |
| country | string ISO country override for the proxy exit, |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Shared shape of the AI Places and AI Shopping finders. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "task": "cheapest Nintendo Switch OLED",
- "country": "it"
}Response samples
- 200
- 400
- 401
- 402
- 429
- 500
- 503
{- "type": "response",
- "message": "Shopping search successful",
- "payload": {
- "products": [
- {
- "title": "Nintendo Switch OLED Bianco",
- "price": "€ 299,00",
- "merchant": "Example Store",
}
], - "total": 24,
- "queries": [
- "Nintendo Switch OLED prezzo"
], - "searches": [
- {
- "query": "Nintendo Switch OLED prezzo",
- "results": 24
}
], - "summary": "Lowest price €299 at Example Store.",
- "model": "gpt-4o-mini",
- "usage": {
- "input_tokens": 7100,
- "output_tokens": 900,
- "cost_usd": 0.0121,
- "free_usd": 0.0121,
- "paid_usd": 0
}
}, - "pagination": { }
}AI visibility audit
Price: ai_visibility $0.01 per call · ai_visibility_citation $0.01 per call · serp $0.0009 per call. ai_visibility + answered (query × engine) × ai_visibility_citation + (2 retrieval + 5 offsite) × serp, only for SERPs that answered. Pre-check reserves the worst case. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Answers one question about a page — can an AI assistant read it, and does it cite it? — on two levels. On-page (always): AI crawler access from the real robots.txt (24 bots), Content-Signal, a fetch that identifies itself as an AI crawler, noindex/nosnippet/noai directives, text without JavaScript, structured data and resolvable entities, citable form (questions, opening answer, lists/tables, numbers, chunk-sized sections), dated and authored content — scored per pillar with blockers that cap the total and the evidence behind every check. Citations (only when queries is given): the questions are really asked to Perplexity, ChatGPT, Claude, Google AI Overview, Bing Copilot and a DeepSeek-over-Google-SERP engine, and the answer reports who is cited or at least mentioned, plus share of voice against competitors. It does not change the page and the citation panel is capped at 10 queries per call and a daily per-account cap on LLM engine calls. Billed as the on-page audit fee plus one ai_visibility_citation per (query × engine) that actually answered, plus serp for the 2 retrievability SERPs and the 5 offsite SERPs when run.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters |
| queries | Array of strings <= 10 items Questions to ask the engines. Absent = on-page audit only. |
| engines | Array of strings Items Enum: "perplexity" "openai" "anthropic" "aio" "copilot" "deepseek" Subset of engines for the citation panel; default all six. |
| competitors | Array of strings <= 20 items Domains to name explicitly in the share of voice. |
| brand | string <= 80 characters Name to look for in answer text ("mentioned"). |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
| no_render | boolean Default: false Skip the rendered pass (cheaper). Alias |
| no_bot_fetch | boolean Default: false Skip the extra request that identifies as an AI crawler. Alias |
| no_retrieval | boolean Default: false Skip the 2 retrievability SERPs (rank for the page's own H1 question, index status). Alias |
| offsite | boolean Default: false Also search the brand on YouTube, Reddit, Wikipedia, LinkedIn and review sites (5 SERPs). |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "queries": [
- "how do I choose a residential proxy provider?"
], - "engines": [
- "perplexity",
- "aio"
], - "brand": "Example"
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "AI visibility audit successful",
- "payload": {
- "domain": "example.com",
- "score": {
- "overall": 71,
- "pillars": {
- "access": 90,
- "content": 68,
- "structure": 60,
- "citability": 66
}, - "scoredPillars": [
- "access",
- "content",
- "structure",
- "citability"
], - "blockers": [ ],
- "uncapped": 71
}, - "checks": [
- {
- "id": "robots_gptbot",
- "pillar": "access",
- "status": "pass",
- "weight": 8,
- "title": "GPTBot allowed",
- "detail": "robots.txt does not disallow GPTBot.",
- "evidence": {
- "rule": null
}
}
], - "topFixes": [
- {
- "id": "author_resolvable",
- "status": "fail",
- "title": "Author not resolvable",
- "fix": "Add an author Person node with url or sameAs."
}
], - "access": {
- "robotsTxtFound": true,
- "blockedCritical": [ ],
- "llmsTxt": false
}, - "content": {
- "contentOnlyInJs": false,
- "fkGrade": 9.1
}, - "structure": {
- "jsonldTypes": [
- "Article"
], - "hasAuthor": true,
- "authorResolvable": false
}, - "citations": {
- "rows": [
- {
- "query": "how do I choose a residential proxy provider?",
- "engine": "perplexity",
- "cited": false,
- "mentioned": true,
- "rank": null,
- "citedDomains": [
- "competitor.example"
]
}
], - "usage": {
- "perplexity": {
- "searches": 1
}
}
}, - "geo": {
- "country": null
}, - "billing": {
- "citation_calls_billed": 2,
- "offsite_serps_billed": 2
}, - "usage": {
- "cost_usd": 0.023,
- "free_usd": 0.023,
- "paid_usd": 0
}
}, - "pagination": { }
}No-JS vs rendered SEO audit
Price: seo_audit $0.003 per call · extract $0.0015 per call + $3/GB, max $0.02 per call. seo_audit when the render pass ran; extract when no_render is true or the render pass errored. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Short alias: POST https://api.quanticdata.io/v1/seo-audit (same handler, primary host only)
Try it in the Playground · Markdown for this group
Fetches a URL twice — once as a pure HTTP bot (no JavaScript) and once fully rendered — and returns what search engines see in each view, the diff (title/description changes, H1 or content only after JS, missing canonical) and the bot-facing meta (robots, OpenGraph, JSON-LD types). It is a page-level technical check, not a site crawl or a keyword tool. The full audit takes one browser-render token; with no_render only the no-JS view is produced and the call bills the plain scrape price. If the render pass fails on our side you still get the no-JS view at the plain scrape price.
Authorizations:
Request Body schema: application/jsonrequired
| url required | string <= 2048 characters |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
| no_render | boolean Default: false Skip the rendered pass. Alias |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "SEO audit successful",
- "payload": {
- "noJs": {
- "status": 200,
- "title": "Example Domain",
- "description": null,
- "canonical": null,
- "h1": "Example Domain",
- "wordCount": 28,
- "hasContent": false
}, - "render": {
- "status": 200,
- "title": "Example Domain",
- "description": null,
- "canonical": null,
- "h1": "Example Domain",
- "wordCount": 28,
- "hasContent": false
}, - "diff": {
- "titleChanged": false,
- "descriptionChanged": false,
- "h1OnlyInRender": false,
- "canonicalMissingNoJs": true,
- "contentOnlyInJs": false
}, - "meta": {
- "robots": null,
- "ogTitle": null,
- "ogUrl": null,
- "twitterCard": null,
- "jsonldTypes": [ ]
}, - "durationMs": 4210,
- "geo": {
- "country": null
}, - "usage": {
- "cost_usd": 0.0012,
- "free_usd": 0.0012,
- "paid_usd": 0
}
}, - "pagination": { }
}Ready-made, versioned scrapers on a semantic input; billed per delivered row. The catalog is dynamic: read it from GET /scraper/collectors.
Collector catalog
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Every ready-made collector with its identity and version, semantic input_schema (JSON Schema — what to POST to run_url), full output_schema, examples, hourly health probe and YOUR price per delivered result (list price × tier discount). The catalog is the source of truth: collectors are added and versioned without an API change, so read it rather than hard-coding slugs. Free.
Authorizations:
query Parameters
| category | string Enum: "search" "seo" "social" "apps" "real_estate" "local" "jobs" "news" "ecommerce" "travel" "leads" "company" "classifieds" "finance" "dev" "knowledge" "gaming" "osint" "research" Only collectors of this category. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/collectors' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 503
{- "type": "response",
- "message": "Collectors",
- "payload": {
- "collectors": [
- {
- "slug": "google_maps_places",
- "name": "Google Maps places",
- "version": "1.1.0",
- "category": "local",
- "category_label": "Local & Maps",
- "tagline": "Businesses for a keyword in a location — name, rating, address, phone, website, coordinates.",
- "description": "Searches Google's local results for a keyword in a location and delivers de-duplicated place records with contact and geo fields.",
- "unit": "place",
- "engines": [
- "serp"
], - "price": {
- "list_usd": 0.001,
- "your_usd": 0.001,
- "price_key": "collector_google_maps_places",
- "per_1k_usd": 1,
- "min_billable_results": 0,
- "min_run_usd": 0
}, - "max_results": 300,
- "input_schema": {
- "type": "object",
- "properties": {
- "query": {
- "type": "string",
- "title": "Keyword",
- "minLength": 2,
- "maxLength": 120,
- "examples": [
- "pizza restaurants"
]
}, - "location": {
- "type": "string",
- "title": "Location",
- "minLength": 2,
- "maxLength": 120,
- "examples": [
- "Brooklyn, NY"
]
}, - "country": {
- "type": "string",
- "format": "country"
}, - "lang": {
- "type": "string",
- "format": "lang"
}, - "max_results": {
- "type": "integer",
- "default": 20,
- "minimum": 1,
- "maximum": 300
}, - "enrich_details": {
- "type": "boolean",
- "default": true
}
}, - "required": [
- "query",
- "location"
], - "additionalProperties": false
}, - "output_schema": {
- "fields": [
- {
- "name": "rank",
- "type": "integer",
- "description": "1-based position across the merged pages."
}, - {
- "name": "name",
- "type": "string",
- "description": "Business name."
}, - {
- "name": "rating",
- "type": "number",
- "nullable": true,
- "description": "Star rating (1–5)."
}, - {
- "name": "place_id",
- "type": "string",
- "nullable": true,
- "description": "Google place id."
}
]
}, - "examples": [
- {
- "title": "Pizza in Brooklyn",
- "input": {
- "query": "pizza restaurants",
- "location": "Brooklyn, NY",
- "country": "us",
- "max_results": 20
}
}
], - "health_input": {
- "query": "pizza",
- "location": "Brooklyn, NY",
- "country": "us",
- "max_results": 10
}, - "health": {
- "status": "healthy",
- "checked_at": "2026-10-07T08:00:12.000Z",
- "latency_ms": 6210,
- "result_count": 10,
- "error": null,
- "success_rate_24h": 1,
- "last_ok_at": "2026-10-07T08:00:12.000Z"
}, - "run_url": "/api/v1/scraper/collectors/google_maps_places/run"
}
], - "billing": {
- "enabled": true,
- "discount_multiplier": 1
}
}, - "pagination": { }
}One collector
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The catalog entry of one collector plus its changelog and the last 24 health probes. Free.
Authorizations:
path Parameters
| slug required | string Example: google_maps_places Collector slug from the catalog. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/collectors/google_maps_places' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 503
{- "type": "response",
- "message": "Collector",
- "payload": {
- "collector": {
- "slug": "google_maps_places",
- "name": "Google Maps places",
- "version": "1.1.0",
- "category": "local",
- "category_label": "Local & Maps",
- "tagline": "Businesses for a keyword in a location.",
- "description": "…",
- "unit": "place",
- "engines": [
- "serp"
], - "price": {
- "list_usd": 0.001,
- "your_usd": 0.001,
- "price_key": "collector_google_maps_places",
- "per_1k_usd": 1,
- "min_billable_results": 0,
- "min_run_usd": 0
}, - "max_results": 300,
- "input_schema": {
- "type": "object",
- "properties": { },
- "required": [
- "query",
- "location"
], - "additionalProperties": false
}, - "output_schema": {
- "fields": [ ]
}, - "examples": [ ],
- "health_input": { },
- "health": {
- "status": "healthy",
- "checked_at": "2026-10-07T08:00:12.000Z",
- "latency_ms": 6210,
- "result_count": 10,
- "error": null,
- "success_rate_24h": 1,
- "last_ok_at": "2026-10-07T08:00:12.000Z"
}, - "run_url": "/api/v1/scraper/collectors/google_maps_places/run",
- "changelog": [
- {
- "version": "1.1.0",
- "date": "2026-08-21",
- "notes": "Paginates past offset 240."
}
], - "health_history": [
- {
- "checked_at": "2026-10-07T08:00:12.000Z",
- "ok": true,
- "latency_ms": 6210,
- "result_count": 10,
- "error": null
}
]
}
}, - "pagination": { }
}Run a collector
Price: collector_result per delivered result, price by collector (see the collector price table). Per delivered row: pricing.json key collector_<slug> when it exists, else collector_result. GET /scraper/collectors returns the resolved key and your discounted price for every collector. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The body is the collector's semantic input exactly as published in its input_schema (flat, or wrapped as {"input": {...}}), plus runner options: async: true forces background processing (also mode: "async" or wait: false). Short runs answer synchronously with the rows; long ones (the collector decides from the input size) answer 202 with a statusUrl to poll. Identical input re-sent inside the dedup window returns the existing run (deduplicated: true) — nothing new is created or charged. Per-account brakes (runs per hour, concurrent runs, failure streak) answer 429 with Retry-After. Billed per DELIVERED row at the collector's unit price × your tier discount (some collectors have a small per-run floor, see price.min_billable_results); zero rows = zero charge, failed runs are never billed. The worst case (unit × max_results) must be covered by free tier + balance or the run is refused with 402.
Authorizations:
path Parameters
| slug required | string Example: google_maps_places Collector slug from the catalog. |
Request Body schema: application/jsonrequired
| async | boolean Default: false Force background processing (202 + statusUrl). |
| mode | string Value: "async" Alias of |
| wait | boolean
|
| input | object Optional wrapper for the collector input. |
| property name* additional property | any |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "query": "pizza restaurants",
- "location": "Brooklyn, NY",
- "country": "us",
- "max_results": 20
}Response samples
- 200
- 202
- 400
- 401
- 402
- 404
- 422
- 424
- 429
- 503
{- "type": "response",
- "message": "Collector run complete",
- "payload": {
- "run_id": "cmgfq2x1b0001",
- "slug": "google_maps_places",
- "version": "1.1.0",
- "status": "done",
- "input": {
- "query": "pizza restaurants",
- "location": "Brooklyn, NY",
- "country": "us",
- "max_results": 20
}, - "count": 20,
- "partial": false,
- "cost": {
- "usd": 0.02,
- "unit_usd": 0.001,
- "unit": "place",
- "billed": true
}, - "error": null,
- "results": [
- {
- "rank": 1,
- "name": "Joe's Pizza",
- "rating": 4.5,
- "reviews": 3120,
- "category": "Pizza restaurant",
- "address": "7 Carmine St, New York, NY 10014",
- "phone": "+1 212-366-1182",
- "website": "joespizzanyc.com",
- "latitude": 40.7306,
- "longitude": -74.0027,
- "place_id": "ChIJ…",
- "data_id": "0x89c259…:0x…",
- "found_by": "pizza restaurants Brooklyn, NY"
}
], - "notes": [ ],
- "created_at": "2026-10-07T09:20:01.000Z",
- "started_at": "2026-10-07T09:20:01.000Z",
- "finished_at": "2026-10-07T09:20:14.000Z",
- "usage": {
- "cost_usd": 0.02,
- "free_usd": 0.02,
- "paid_usd": 0
}
}, - "pagination": { }
}Your collector runs
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Newest first, without result rows. Page with next_cursor. Free.
Authorizations:
query Parameters
| limit | integer [ 1 .. 100 ] Default: 20 |
| cursor | string
|
| slug | string Only runs of this collector. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/collectors/runs' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 503
{- "type": "response",
- "message": "Collector runs",
- "payload": {
- "runs": [
- {
- "run_id": "cmgfq2x1b0001",
- "slug": "google_maps_places",
- "version": "1.1.0",
- "status": "done",
- "input": {
- "query": "pizza restaurants",
- "location": "Brooklyn, NY"
}, - "count": 20,
- "partial": false,
- "cost": {
- "usd": 0.02,
- "unit_usd": 0.001,
- "unit": "place",
- "billed": true
}, - "error": null,
- "created_at": "2026-10-07T09:20:01.000Z",
- "started_at": "2026-10-07T09:20:01.000Z",
- "finished_at": "2026-10-07T09:20:14.000Z"
}
], - "next_cursor": null
}, - "pagination": { }
}One run with its rows
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The run you own with its delivered results. format=csv streams the rows as CSV (columns follow the collector's output_schema). Free.
Authorizations:
path Parameters
| runId required | string^[a-z0-9]{10,40}$ Example: cmgfq2x1b0001 Collector run id (10–40 alphanumeric characters). |
query Parameters
| format | string Value: "csv"
|
Responses
Response Schema:
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/collectors/runs/cmgfq2x1b0001' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 503
{- "type": "response",
- "message": "Collector run",
- "payload": {
- "run_id": "cmgfq2x1b0001",
- "slug": "google_maps_places",
- "version": "1.1.0",
- "status": "done",
- "input": {
- "query": "pizza restaurants",
- "location": "Brooklyn, NY",
- "country": "us",
- "max_results": 20
}, - "count": 20,
- "partial": false,
- "cost": {
- "usd": 0.02,
- "unit_usd": 0.001,
- "unit": "place",
- "billed": true
}, - "error": null,
- "results": [
- {
- "rank": 1,
- "name": "Joe's Pizza"
}
], - "created_at": "2026-10-07T09:20:01.000Z",
- "started_at": "2026-10-07T09:20:01.000Z",
- "finished_at": "2026-10-07T09:20:14.000Z",
- "usage": {
- "cost_usd": 0.02,
- "free_usd": 0.02,
- "paid_usd": 0
}
}, - "pagination": { }
}Your recent dataset runs
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The last 20 runs, newest first, with status reconciled against the live job for runs still marked running, the settled cost, and whether the rows are still stored. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/datasets' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 503
{- "type": "response",
- "message": "Datasets",
- "payload": {
- "datasets": [
- {
- "id": "cmgf0",
- "jobId": "ds_7a1c22",
- "name": null,
- "prompt": "Car rental companies in Bologna with phone and website",
- "columns": "[{\"name\":\"company\",\"type\":\"string\"},{\"name\":\"phone\",\"type\":\"phone\"},{\"name\":\"website\",\"type\":\"url\"}]",
- "country": "it",
- "status": "completed",
- "rowCount": 42,
- "billableRows": 40,
- "refresh": false,
- "createdAt": "2026-10-06T14:02:11.000Z",
- "completedAt": "2026-10-06T14:09:40.000Z",
- "purgedAt": null,
- "costUsd": 1.86,
- "stored": true,
- "storedRows": 42,
- "storedBytes": 18311,
- "purged": false,
- "dropped": null
}
]
}, - "pagination": { }
}Build a dataset from a prompt
Price: dataset_row $0.03 per call · dataset_row_refresh $0.01 per call. max_cost_usd charged up front, refunded down to actual spend. Actual spend = delivered validated rows × dataset_row (dataset_row_refresh on refresh) + premium field fees + metered pipeline units (serp/map/extract/AI). (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
One plain-language prompt → a structured dataset. The service plans queries, searches, maps and scrapes, extracts the requested columns and returns validated rows; refresh: true re-reads a known URL set (refreshUrls) without discovery at a reduced row fee. Returns a job id immediately; poll GET /scraper/datasets/{jobId}, download the file, or pass a webhook (public host only, delivered after settlement with the hygiene filters applied). Billing is value-based: the run's budget limits.max_cost_usd (default $5, max $500, min $0.05) is charged up front and the unspent share is refunded at settlement, so you pay only for delivered, validated records (dataset_row, or dataset_row_refresh on a refresh) plus premium columns found (email, phone, deep) plus the pipeline units consumed. Low-confidence rows, off-target pages and blocked pages are never billed.
Authorizations:
Request Body schema: application/jsonrequired
| prompt required | string <= 2000 characters What the dataset is. |
Array of objects Omit to let the planner infer columns from the prompt. | |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
object Domain allow/deny lists. | |
object | |
| webhook | string <= 2048 characters Public http(s) URL that receives the finished, filtered dataset by POST. |
| refresh | boolean Default: false |
| refreshUrls | Array of strings <= 1000 items [ items <= 2048 characters ] Required with |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Answer of a POST that started an async job. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "prompt": "Car rental companies in Bologna with phone and website",
- "columns": [
- {
- "name": "company",
- "type": "string"
}, - {
- "name": "phone",
- "type": "phone"
}, - {
- "name": "website",
- "type": "url"
}
], - "country": "it",
- "limits": {
- "max_rows": 50,
- "max_cost_usd": 3
}
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Dataset started",
- "payload": {
- "id": "ds_7a1c22",
- "status": "running",
- "prompt": "Car rental companies in Bologna with phone and website",
- "columns": [
- {
- "name": "company",
- "type": "string"
}, - {
- "name": "phone",
- "type": "phone"
}, - {
- "name": "website",
- "type": "url"
}
], - "limits": {
- "max_rows": 50,
- "max_pages": 200,
- "max_cost_usd": 3
}, - "statusUrl": "/api/v1/scraper/datasets/ds_7a1c22",
- "usage": {
- "cost_usd": 3,
- "free_usd": 2,
- "paid_usd": 1,
- "balance": 9
}
}, - "pagination": { }
}Poll a dataset job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Progress, the collection trace (steps) and the rows so far, filtered for you (removal list, your exclusion list, rows already delivered to you). A run the service has already forgotten (about an hour after it finishes) is served from storage (source: storage, no progress/steps). Free.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
query Parameters
| since | integer Row cursor from the previous poll's |
| mode | string Value: "summary"
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Live job view (from the service) or the stored view of a finished run ( |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/datasets/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Dataset status",
- "payload": {
- "id": "ds_7a1c22",
- "status": "completed",
- "prompt": "Car rental companies in Bologna with phone and website",
- "columns": [
- {
- "name": "company",
- "type": "string"
}, - {
- "name": "phone",
- "type": "phone"
}, - {
- "name": "website",
- "type": "url"
}
], - "files": null,
- "progress": {
- "queries_run": 6,
- "sites_mapped": 12,
- "pages_scraped": 58,
- "pages_failed": 3,
- "rows": 42,
- "dropped_offtarget": 4,
- "cost_so_far_usd": 1.86
}, - "limits": {
- "max_rows": 50,
- "max_pages": 200,
- "max_cost_usd": 3
}, - "entity": "car rental company",
- "billable": {
- "row_fees_usd": 1.62,
- "unit_usd": 0.24
}, - "steps": [
- {
- "phase": "plan",
- "detail": "entity: car rental company; 6 queries",
- "ts": 1759759331000
}
], - "rows": [
- {
- "_fetched_at": "2026-10-06T14:05:10.000Z",
- "confidence": 0.93,
- "billed_fields": [
- "phone"
], - "fee_usd": 0.05
}
], - "row_count": 42,
- "billable_rows": 40,
- "nextCursor": 42,
- "createdAt": 1759759331000,
- "finishedAt": 1759759780000
}, - "pagination": { }
}Cancel a dataset job
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Stops a running job you own; the unspent budget is refunded at settlement. To delete the stored record of a finished run use DELETE /scraper/datasets/{jobId}/record.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/datasets/job_8f2c1a' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Dataset cancelled",
- "payload": {
- "id": "ds_7a1c22",
- "status": "cancelled"
}, - "pagination": { }
}Download a dataset file
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The run's rows as CSV or JSON, partial runs included (rows collected before an interruption are delivered too). Always built from rows that passed the list-hygiene filter. 404 while the run is still going or when it produced no rows. Free.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
query Parameters
| format | string Default: "csv" Enum: "csv" "json" |
Responses
Response Schema:
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/datasets/job_8f2c1a/download' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 500
- 503
company,phone,website,_source_url Bologna Rent,+39 051 000000,https://example.it,https://example.it/contatti
Rename a dataset run
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Sets the run's label (max 120 characters); an empty string or null clears it and the prompt becomes the label again. The prompt itself is never rewritten. Free.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Request Body schema: application/jsonrequired
| name | string or null <= 120 characters |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "name": "Bologna car rentals — October"
}Response samples
- 200
- 400
- 401
- 404
- 429
- 503
{- "type": "response",
- "message": "Dataset renamed",
- "payload": {
- "jobId": "ds_7a1c22",
- "name": "Bologna car rentals — October",
- "prompt": "Car rental companies in Bologna with phone and website"
}, - "pagination": { }
}Delete a dataset run's stored record
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Permanently removes the record and its stored rows. A run still in flight must be cancelled first (400). Irreversible. Free.
Authorizations:
path Parameters
| jobId required | string Example: job_8f2c1a Job id returned by the POST that started it. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/datasets/job_8f2c1a/record' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 503
{- "type": "response",
- "message": "Dataset deleted",
- "payload": {
- "jobId": "ds_7a1c22"
}, - "pagination": { }
}Generate CSS selectors with an LLM, once
Price: parser_generate $0.02 per call. parser_generate, only when coverage > 0. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Looks at a page once with a model and returns CSS selectors (parser) that extract the fields you asked for — ready to pass as extract on every later scrape of that layout, where no model is involved and the plain scrape price applies. Every selector is run against the page before it is returned: report, missed and coverage tell you which fields are reliable. Give url (fetched through the pool, render: true for SPA pages) or html you already have (max 3 MB, no proxy bandwidth). Charged once as a setup step, and only when the parser extracts something (coverage > 0).
Authorizations:
Request Body schema: application/jsonrequired
| url | string <= 2048 characters Required unless |
| html | string |
object <= 25 properties field name → what it is. Required unless | |
| prompt | string <= 2000 characters Free-text alternative to |
| render | boolean Default: false |
| country | string (GeoValue) ^([a-zA-Z0-9 ._-]{1,56}|all)$ Examples: "us" "it" "all" Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "fields": {
- "title": "product name",
- "price": "current price with currency",
- "sku": "SKU code"
}
}Response samples
- 200
- 400
- 401
- 402
- 403
- 429
- 500
- 503
{- "type": "response",
- "message": "Parser generated",
- "payload": {
- "parser": {
- "title": "h1.product-title",
- "price": {
- "selector": "span.price",
- "attr": null
}, - "sku": "dd.sku"
}, - "report": [
- {
- "field": "title",
- "selector": "h1.product-title",
- "sample": "Trail Runner 2",
- "missed": false
}, - {
- "field": "price",
- "selector": "span.price",
- "sample": "€ 129,00",
- "missed": false
}, - {
- "field": "sku",
- "selector": "dd.sku",
- "sample": "TR2-42",
- "missed": false
}
], - "missed": [ ],
- "coverage": 1,
- "repaired": false,
- "usage": {
- "cost_usd": 0.02,
- "free_usd": 0.02,
- "paid_usd": 0
}
}, - "pagination": { }
}List your presets
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Every stored parser of your account with its stats and version history. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/parser/presets' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 500
- 503
{- "type": "response",
- "message": "Presets",
- "payload": {
- "presets": [
- {
- "id": "pst_7Qk3",
- "name": "example-product",
- "fields": {
- "title": "product name",
- "price": "current price"
}, - "render": false,
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "version": 1,
- "autoHeal": true,
- "createdAt": 1759759331000,
- "updatedAt": 1759759331000,
- "lastHealAt": null,
- "stats": {
- "runs": 12,
- "lastRunAt": 1759830000000,
- "fields": {
- "title": {
- "hits": 12,
- "misses": 0
}, - "price": {
- "hits": 11,
- "misses": 1
}
}, - "recent": [
- 1,
- 1,
- 0.5,
- 1
]
}, - "history": [
- {
- "version": 1,
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "at": 1759759331000,
- "reason": "created",
- "coverage": 1
}
]
}
]
}, - "pagination": { }
}Save a parser as a preset
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Stores a parser (usually the one /scraper/parser/generate just returned) under a name. Scrape with presetId instead of an inline extract schema and every run is scored per field; when the recent success rate decays and autoHeal is on, the preset regenerates itself from sourceUrl and bumps its version. Ownership is server-side: a client-supplied tenant is ignored. Free to store.
Authorizations:
Request Body schema: application/jsonrequired
| name required | string <= 120 characters |
required | object (ExtractSchema) Examples: {"title":"h1","price":".price","image":{"selector":"img.hero","attr":"src"},"features":{"selector":"li.feature","all":true}} Non-empty, at most 25 fields. |
| sourceUrl | string <= 2048 characters Page the parser was learned from — self-healing refetches it. |
object field → description, so a heal can regenerate the same shape. | |
| render | boolean Default: false |
| autoHeal | boolean |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "name": "example-product",
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "fields": {
- "title": "product name",
- "price": "current price"
}, - "autoHeal": true
}Response samples
- 200
- 400
- 401
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset created",
- "payload": {
- "id": "pst_7Qk3",
- "name": "example-product",
- "fields": {
- "title": "product name",
- "price": "current price"
}, - "render": false,
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "version": 1,
- "autoHeal": true,
- "createdAt": 1759759331000,
- "updatedAt": 1759759331000,
- "lastHealAt": null,
- "stats": {
- "runs": 0,
- "lastRunAt": null,
- "fields": { },
- "recent": [ ]
}, - "history": [
- {
- "version": 1,
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "at": 1759759331000,
- "reason": "created"
}
]
}, - "pagination": { }
}Read a preset
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Parser, stats and version history. A preset belonging to someone else answers 404. Free.
Authorizations:
path Parameters
| id required | string Example: pst_7Qk3 Preset id returned when it was created. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/parser/presets/pst_7Qk3' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset",
- "payload": {
- "id": "pst_7Qk3",
- "name": "example-product",
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "version": 1,
- "autoHeal": true,
- "createdAt": 1759759331000,
- "updatedAt": 1759759331000,
- "lastHealAt": null,
- "stats": {
- "runs": 12,
- "lastRunAt": 1759830000000,
- "fields": { },
- "recent": [ ]
}, - "history": [ ]
}, - "pagination": { }
}Update a preset
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Rename, replace the parser (bumps the version), toggle autoHeal, update fields/sourceUrl. Only the keys you send change. Free.
Authorizations:
path Parameters
| id required | string Example: pst_7Qk3 Preset id returned when it was created. |
Request Body schema: application/jsonrequired
| name | string |
object (ExtractSchema) Examples: {"title":"h1","price":".price","image":{"selector":"img.hero","attr":"src"},"features":{"selector":"li.feature","all":true}} Non-empty, at most 25 fields. | |
| autoHeal | boolean |
object | |
| sourceUrl | string |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "autoHeal": false
}Response samples
- 200
- 400
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset updated",
- "payload": {
- "id": "pst_7Qk3",
- "name": "example-product",
- "parser": {
- "title": "h1.product-title",
- "price": "span.price"
}, - "version": 1,
- "autoHeal": false,
- "createdAt": 1759759331000,
- "updatedAt": 1759840000000,
- "lastHealAt": null,
- "stats": {
- "runs": 12,
- "lastRunAt": 1759830000000,
- "fields": { },
- "recent": [ ]
}, - "history": [ ]
}, - "pagination": { }
}Delete a preset
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Removes the preset and its version history. Scrapes that still send its presetId answer 404 afterwards. Free.
Authorizations:
path Parameters
| id required | string Example: pst_7Qk3 Preset id returned when it was created. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/scraper/parser/presets/pst_7Qk3' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset deleted",
- "payload": {
- "ok": true
}, - "pagination": { }
}Regenerate a preset's parser now
Price: parser_generate $0.02 per call. parser_generate only when healed is true. (list of 2026-10-19)
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The manual trigger of the repair that runs automatically when a preset decays: refetches sourceUrl, asks the model for fresh selectors and adopts them only if they extract more of the page than the current ones. force: true bypasses the cooldown between heals. Billed like a generation, and only when a new version was actually produced (healed: true).
Authorizations:
path Parameters
| id required | string Example: pst_7Qk3 Preset id returned when it was created. |
Request Body schema: application/jsonoptional
| force | boolean Default: false |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "force": false
}Response samples
- 200
- 400
- 401
- 402
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset healed",
- "payload": {
- "healed": true,
- "reason": "coverage improved",
- "version": 2,
- "coverageBefore": 0.5,
- "coverageAfter": 1,
- "parser": {
- "title": "h1[itemprop=name]",
- "price": "span.price-now"
}, - "usage": {
- "cost_usd": 0.02,
- "free_usd": 0.02,
- "paid_usd": 0
}
}, - "pagination": { }
}How well a preset still works
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Lifetime success rate per field, mean coverage over the recent window and whether the preset now counts as decayed (the signal that triggers self-healing). Free — it is the health check of a parser you already paid to build.
Authorizations:
path Parameters
| id required | string Example: pst_7Qk3 Preset id returned when it was created. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/parser/presets/pst_7Qk3/stats' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 404
- 429
- 500
- 503
{- "type": "response",
- "message": "Preset stats",
- "payload": {
- "id": "pst_7Qk3",
- "name": "example-product",
- "version": 2,
- "runs": 12,
- "lastRunAt": 1759830000000,
- "successRateByField": {
- "title": 1,
- "price": 0.917
}, - "recentCoverage": 0.96,
- "decayed": false,
- "autoHeal": true,
- "lastHealAt": 1759840000000
}, - "pagination": { }
}List your proxy plans, generate endpoint strings, manage IP whitelists, and get a new IP on demand. Limits: generate returns 1 to 10000 lines per call; the number of whitelisted IPs per plan is the plan's whitelistSlots; ip-info shares a lookup budget of about 45 calls a minute. Every call also counts in the hourly window of your API key (see Rate limits and tiers).
New IP on demand. A rotating string changes IP on every request. A sticky string keeps one IP for its session (sessionTime in generate). On Residential Basic and Datacenter traffic plans you can restart a sticky session at any time: the same string leaves from a new IP on its next request, so a saved anti-detect profile or a script keeps its proxy settings. Call POST /public/proxies/{orderId}/rotate with your API key, or create a rotation link: a URL with no key and no header that anti-detect browsers and scripts can call directly.
Plan type (planType) |
Rotating strings | Sticky strings | New IP on demand |
|---|---|---|---|
residentialbasic, datacentertraffic |
New IP per request | Same IP for sessionTime |
rotate or a rotation link: same string, new IP |
residentialpremium, resiprivate, mobile_v2, mobile, ipv6 |
New IP per request | Same IP for sessionTime |
Request a new sticky string with generate |
datacenter |
Assigned by the gateway | Assigned by the gateway | Not applicable |
isp, isppremium |
Static IPs | Static IPs | Not applicable: dedicated static IPs |
Build proxy strings with generate and use them as returned; do not edit them by hand.
List your proxy plans
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Every proxy service on the account (residential basic/premium/private, ISP, premium ISP, datacenter, datacenter traffic, IPv6, mobile, mobile v2) with credentials, bandwidth left, expiry and the orderId the generate and whitelist endpoints take. Free; no Data API billing. Plans disabled by support are not listed. Premium ISP plans (planType: isppremium, bought in the dashboard or with POST /public/premium-isp/orders) are both the ready-made pool plans and the city plans (City and carrier, Fraud score 0). They have no plan-level login (username and password are empty strings): every dedicated IP has its own login, returned by POST /public/proxies/generate, and ips is the number of IPs. IP whitelisting and credential changes are not available on Premium ISP plans. City plans report region as premium-isp-city, or premium-isp-city-fraud-score-0 for Fraud score 0 plans. Premium ISP IPs reach only ports 80 and 443. Pool plans also cannot open banking, payment or government sites; city plans (Fraud score 0 included) have no site blocks (see the Terms of Service).
Authorizations:
query Parameters
| limit | integer <= 100 Default: 50 |
| offset | integer Default: 0 |
| planType | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" |
| active | string Enum: "true" "false" Filter by expiry; omit for all. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/proxies' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 429
- 500
{- "type": "response",
- "message": "Success",
- "payload": {
- "proxies": [
- {
- "id": "prx_1",
- "orderId": "ord_8c21",
- "planName": "Residential Premium 5 GB",
- "planType": "residentialpremium",
- "planTypeName": "Residential Premium",
- "username": "user_8c21",
- "password": "p4ssw0rd",
- "bandwidth": 5,
- "bandwidthGB": 5,
- "bandwidthLeft": 3.2,
- "bandwidthLeftGB": 3.2,
- "bandwidthUsed": 1.8,
- "bandwidthUsedGB": 1.8,
- "bandwidthUsagePercent": 36,
- "isUnlimited": false,
- "expiry": "2026-11-06T00:00:00.000Z",
- "expiresAt": "2026-11-06T00:00:00.000Z",
- "isActive": true,
- "isExpired": false,
- "daysRemaining": 30,
- "hoursRemaining": 720,
- "ips": 0,
- "whitelistSlots": 0,
- "whitelistedIPs": [ ],
- "region": "Global",
- "speed": null,
- "highConcurrency": false,
- "highPriority": false,
- "createdAt": "2026-10-06T10:00:00.000Z"
}
], - "pagination": {
- "total": 1,
- "limit": 50,
- "offset": 0,
- "hasMore": false
}
}, - "pagination": { }
}Generate proxy strings for a plan
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Ready-to-use endpoint strings (credentials included) for one order, in HTTP or SOCKS5 and several formats, with the targeting the plan supports: country/state/city for residential and mobile, ISP code for Residential Premium and Mobile V2, ASN for Residential Basic and traffic-based Datacenter, static gateways for Datacenter. rotation: sticky keeps one IP for sessionTime minutes; static (IPv6 only) is a fixed session with no TTL. Mobile V2 can alternatively return the IP-auth proxy list for a whitelisted ip. Premium ISP orders still being provisioned answer 202 with pending: true. Premium ISP plans (pool and city) return one line per dedicated IP, each with its own login, and ignore targeting and rotation; quantity caps the number of lines (default 10), so pass the plan's ips to get every IP. ipAddresses holds the exit IP of each line, in the same order as proxies. City plans use one port for both HTTP and SOCKS5, and the host of a city line is a connection server that can change: generate the lines again instead of storing the host. The username of each line carries its targeting and session: generate new lines to change them instead of editing the strings by hand. Which parameters apply depends on the plan type — unsupported ones are ignored, not rejected. Free; no Data API billing (the plan's own bandwidth is consumed when you use the proxies).
Authorizations:
Request Body schema: application/jsonrequired
| orderId required | string From GET /public/proxies. |
| protocol | string Default: "http" Enum: "http" "socks5" |
| format | string Default: "user:pass@host:port" Enum: "user:pass@host:port" "host:port:user:pass" "http://user:pass@host:port" "socks5://user:pass@host:port"
|
| quantity | integer [ 1 .. 10000 ] Default: 10 |
| country | string Lowercase country code (e.g. |
| state | string Region slug (Residential Premium / Mobile V2: from the location tree). Alias |
| city | string City slug. |
| rotation | string Default: "rotating" Enum: "rotating" "sticky" "static"
|
| sessionTime | integer [ 1 .. 1440 ] Default: 10 Sticky session minutes (Residential Basic / Datacenter traffic: min 3 enforced by the gateway). |
| isp | string ISP code (Residential Premium / Mobile V2) or carrier ASN (Mobile). |
| asn | string ASN, e.g. |
| strict | boolean Default: false Residential/Datacenter Basic: |
| filter | string Enum: "speed" "speed-quality" "quality" Residential Premium / Mobile V2 pool filter (default: max pool). |
| isExtension | boolean Default: false Rewrite hostnames with a unique prefix so a browser extension cannot cache the proxy (needs the wildcard DNS of the gateway). |
| ip | string Mobile V2: a whitelisted IP — returns the IP-auth proxy list instead of user:pass strings. |
| gateway | string Default: "ww" Enum: "ww" "us" "eu" "as" Mobile V2 region gateway. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "orderId": "ord_8c21",
- "protocol": "http",
- "format": "user:pass@host:port",
- "quantity": 2,
- "country": "us",
- "rotation": "sticky",
- "sessionTime": 10
}Response samples
- 200
- 202
- 400
- 401
- 403
- 404
- 429
- 500
- 502
{- "type": "response",
- "message": "success",
- "payload": {
- "orderId": "ord_8c21",
- "quantity": 2,
- "protocol": "http",
- "format": "user:pass@host:port",
- "rotation": "sticky",
- "sessionTime": 10,
- "geoTargeting": {
- "country": "us",
- "state": null,
- "city": null
}, - "proxies": [
- "user_8c21-country-us-sid-k3f9a1b2c3d4-ttl-10m:p4ssw0rd@residentialpremium.quantumproxies.io:8080",
- "user_8c21-country-us-sid-q7w2e5r8t1y4-ttl-10m:p4ssw0rd@residentialpremium.quantumproxies.io:8080"
], - "bandwidth": 5,
- "bandwidthLeft": 3.2,
- "whitelist": [ ]
}, - "pagination": { }
}Geolocate an IP
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Country, region, city, coordinates, timezone, ISP and ASN of an IP address — useful to verify where a sticky session actually exits. Served by a third-party geolocation source with its own fair-use limit (about 45 lookups/minute shared). Free.
Authorizations:
query Parameters
| ip required | string Example: ip=203.0.113.7 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/proxies/ip-info?ip=203.0.113.7' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 429
- 500
{- "type": "response",
- "message": "Success",
- "payload": {
- "ip": "203.0.113.7",
- "country": "United States",
- "countryCode": "US",
- "flag": "🇺🇸",
- "region": "California",
- "regionCode": "CA",
- "city": "Los Angeles",
- "zip": "90001",
- "lat": 34.05,
- "lon": -118.24,
- "timezone": "America/Los_Angeles",
- "isp": "Example Telecom",
- "org": "Example Telecom LLC",
- "as": "AS64496 Example Telecom"
}, - "pagination": { }
}List whitelisted IPs of an order
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The IPs allowed to use an IP-auth plan without credentials. Mobile V2 plans also return the detailed upstream entries (ports, geo, sticky) under entries. Free.
Authorizations:
query Parameters
| orderId required | string |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/proxies/whitelist-ip?orderId=ORDERID' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 404
- 429
- 500
{- "type": "response",
- "message": "Success",
- "payload": {
- "orderId": "ord_8c21",
- "whitelist_ip": [
- "203.0.113.7"
]
}, - "pagination": { }
}Whitelist an IP
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Allows an IPv4 address to use the plan by IP authentication. Supported on Residential Basic, Datacenter (both kinds), ISP (planType: isp), IPv6 and Mobile V2; Residential Premium/Private and Premium ISP (isppremium, pool and city plans) authenticate by user:pass only and answer 200 with whitelisted: false and the message Whitelist not required for this proxy type (use username:password auth). Mobile V2 accepts extra port/targeting options and action: update to edit an existing entry. Free.
Authorizations:
Request Body schema: application/jsonrequired
| orderId required | string |
| ip required | string^(\d{1,3}\.){3}\d{1,3}$ IPv4 address. |
| action | string Default: "add" Enum: "add" "update" Mobile V2 only: |
| ports_count | integer [ 1 .. 1000 ] Mobile V2: ports to allocate. |
| protocol | string Enum: "HTTP" "SOCKS5" Mobile V2. |
| country | string Mobile V2 geo targeting for the allocated ports. |
| region | string Mobile V2. |
| city | string Mobile V2. |
| isp | string Mobile V2. |
| sticky | boolean Mobile V2: keep the same IP per port. |
| ttl | integer Mobile V2: sticky session TTL in seconds. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "orderId": "ord_8c21",
- "ip": "203.0.113.7"
}Response samples
- 200
- 400
- 401
- 403
- 404
- 429
- 500
{- "type": "response",
- "message": "IP whitelisted successfully",
- "payload": {
- "ip": "203.0.113.7",
- "whitelisted": true,
- "whitelist_ip": [
- "203.0.113.7"
]
}, - "pagination": { }
}Remove a whitelisted IP
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Removes the IP from the plan's IP-auth list (Mobile V2 also accepts the entry id). Plans that authenticate by user:pass (Residential Premium/Private, Premium ISP) answer 200 with removed: false. Free.
Authorizations:
Request Body schema: application/jsonrequired
| orderId required | string |
| ip required | string |
| id | string Mobile V2 entry id (alternative handle). |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
| payload required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "orderId": "ord_8c21",
- "ip": "203.0.113.7"
}Response samples
- 200
- 400
- 401
- 403
- 404
- 429
- 500
{- "type": "response",
- "message": "IP removed from whitelist",
- "payload": {
- "ip": "203.0.113.7",
- "removed": true,
- "whitelist_ip": [ ]
}, - "pagination": { }
}Rotate a sticky session (new IP, same string)
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Restarts one sticky session of a Residential Basic or Datacenter traffic plan: the same proxy string leaves from a new IP on its next request. Send the sticky string as generate returned it (proxy), or its sessionId with protocol. Wait for the 200 before the next request. One rotation every 10 seconds per session and 1,200 rotations an hour per account (shared with rotation links), on top of the key's hourly window. Other plan types answer 409 ROTATION_NOT_SUPPORTED with a reason that says what to do instead. Errors carry a stable payload.code. Free; no Data API billing.
Authorizations:
path Parameters
| orderId required | string Example: ord_8c21 Order id of the plan ( |
Request Body schema: application/jsonrequired
| proxy | string <= 2048 characters A sticky proxy string of this plan, exactly as |
| sessionId | string^[A-Za-z0-9]{1,32}$ Instead of |
| protocol | string Default: "http" Enum: "http" "socks5" With |
| port | integer With |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object A restarted sticky session. The next request on the same proxy string gets a new IP. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "proxy": "user_8c21-country-us-session-a1b2c3-time-10:p4ssw0rd@residential-ww.quanticdata.io:9999"
}Response samples
- 200
- 400
- 401
- 403
- 404
- 409
- 410
- 429
- 502
- 503
{- "type": "response",
- "message": "Session rotated. The next request on this proxy string gets a new IP.",
- "payload": {
- "rotated": true,
- "orderId": "ord_8c21",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "rotatedAt": "2026-10-19T14:05:00.000Z",
- "nextAllowedAt": "2026-10-19T14:05:10.000Z"
}, - "pagination": { }
}List rotation links of a plan
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The plan's rotation links, newest first, without their tokens (only the last 4 characters, tokenHint): a link URL is shown once, when it is created. Revoked links are left out unless includeRevoked=true. Works on expired plans too, so you can revoke their links. Free.
Authorizations:
path Parameters
| orderId required | string Example: ord_8c21 Order id of the plan ( |
query Parameters
| includeRevoked | boolean Default: false Include revoked links. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/proxies/ord_8c21/rotation-links' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "orderId": "ord_8c21",
- "planType": "residentialbasic",
- "links": [
- {
- "id": "rlk_3f9a1c7e5b2d4a6c8e0f1a2b",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "label": "Profile 12",
- "tokenHint": "1d0e",
- "useCount": 14,
- "lastUsedAt": "2026-10-19T14:05:00.000Z",
- "createdAt": "2026-10-19T14:05:00.000Z",
- "revoked": false,
- "revokedAt": null
}
], - "limits": {
- "activeLinksPerPlan": 1000,
- "cooldownSeconds": 10
}
}, - "pagination": { }
}Create rotation links
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Creates one rotation link per sticky session of a Residential Basic or Datacenter traffic plan: a URL that restarts the session when called, with no API key and no header, for anti-detect browsers and scripts. Send one sticky string (proxy), up to 100 (proxies), or a sessionId with protocol. The url and token appear in this answer only: store them now. Only a hash of the token is kept. Up to 1,000 active links per plan; creating another link for the same session leaves the earlier ones working until you revoke them. Free.
Authorizations:
path Parameters
| orderId required | string Example: ord_8c21 Order id of the plan ( |
Request Body schema: application/jsonrequired
| proxy | string <= 2048 characters A sticky proxy string of this plan, exactly as |
| sessionId | string^[A-Za-z0-9]{1,32}$ Instead of |
| protocol | string Default: "http" Enum: "http" "socks5" With |
| port | integer With |
| proxies | Array of strings [ 1 .. 100 ] items [ items <= 2048 characters ] Several sticky proxy strings of this plan: one link per string. |
| label | string <= 64 characters Optional name stored on every link created by this call: letters, digits, spaces and . _ : # / - |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "proxy": "user_8c21-country-us-session-a1b2c3-time-10:p4ssw0rd@residential-ww.quanticdata.io:9999",
- "label": "Profile 12"
}Response samples
- 201
- 400
- 401
- 403
- 404
- 409
- 410
- 429
- 503
{- "type": "response",
- "message": "Rotation links created. Save each url now: it is not shown again.",
- "payload": {
- "orderId": "ord_8c21",
- "links": [
- {
- "id": "rlk_3f9a1c7e5b2d4a6c8e0f1a2b",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "label": "Profile 12",
- "tokenHint": "1d0e",
- "useCount": 0,
- "lastUsedAt": null,
- "createdAt": "2026-10-19T14:05:00.000Z",
- "revoked": false,
- "revokedAt": null,
- "token": "rl_6f1c0e2b9a7d4c3e8f5a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e"
}
]
}, - "pagination": { }
}Revoke a rotation link
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Revokes the link at once: its URL answers 410 LINK_REVOKED from then on. The proxy string and the plan's other links keep working. Revoking a link twice answers the same revoked link. Free.
Authorizations:
path Parameters
| orderId required | string Example: ord_8c21 Order id of the plan ( |
| linkId required | string Example: rlk_3f9a1c7e5b2d4a6c8e0f1a2b Link id ( |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X DELETE 'https://api.quanticdata.io/v1/public/proxies/ord_8c21/rotation-links/rlk_3f9a1c7e5b2d4a6c8e0f1a2b' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Rotation link revoked.",
- "payload": {
- "link": {
- "id": "rlk_3f9a1c7e5b2d4a6c8e0f1a2b",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "label": "Profile 12",
- "tokenHint": "1d0e",
- "useCount": 14,
- "lastUsedAt": "2026-10-19T14:05:00.000Z",
- "createdAt": "2026-10-19T14:05:00.000Z",
- "revoked": true,
- "revokedAt": "2026-10-19T14:05:10.000Z"
}
}, - "pagination": { }
}Call a rotation link
Price: No charge.
Rate limit: One rotation every 10 seconds per session and 1,200 rotations an hour per account, shared with the rotate endpoint. An address that sends 30 unknown links in 10 minutes is blocked for 10 minutes.
Try it in the Playground · Markdown for this group
The rotation link itself, as returned in url by POST /public/proxies/{orderId}/rotation-links: no API key, no header, no body. Restarts the link's sticky session, so the same proxy string leaves from a new IP on its next request. GET and POST behave the same; HEAD answers 405 without rotating, so link previews do not trigger it. Treat the URL like a password: it can rotate that one session, nothing else (no credentials, no balance). Revoke it with DELETE /public/proxies/{orderId}/rotation-links/{linkId}. Errors carry a stable payload.code. Free.
path Parameters
| token required | string^rl_[a-f0-9]{64}$ Example: rl_6f1c0e2b9a7d4c3e8f5a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e The token at the end of the link URL. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object A restarted sticky session. The next request on the same proxy string gets a new IP. |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/rotate/rl_6f1c0e2b9a7d4c3e8f5a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e'
Response samples
- 200
- 403
- 404
- 409
- 410
- 429
- 502
- 503
{- "type": "response",
- "message": "Session rotated. The next request on this proxy string gets a new IP.",
- "payload": {
- "rotated": true,
- "orderId": "ord_8c21",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "rotatedAt": "2026-10-19T14:05:00.000Z",
- "nextAllowedAt": "2026-10-19T14:05:10.000Z",
- "linkId": "rlk_3f9a1c7e5b2d4a6c8e0f1a2b",
- "label": "Profile 12"
}, - "pagination": { }
}Call a rotation link (POST)
Price: No charge.
Rate limit: One rotation every 10 seconds per session and 1,200 rotations an hour per account, shared with the rotate endpoint. An address that sends 30 unknown links in 10 minutes is blocked for 10 minutes.
Try it in the Playground · Markdown for this group
Same as GET /public/rotate/{token}, for tools that can only send POST. No API key, no header, no body.
path Parameters
| token required | string^rl_[a-f0-9]{64}$ Example: rl_6f1c0e2b9a7d4c3e8f5a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e The token at the end of the link URL. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object A restarted sticky session. The next request on the same proxy string gets a new IP. |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X POST 'https://api.quanticdata.io/v1/public/rotate/rl_6f1c0e2b9a7d4c3e8f5a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e'
Response samples
- 200
- 403
- 404
- 409
- 410
- 429
- 502
- 503
{- "type": "response",
- "message": "Session rotated. The next request on this proxy string gets a new IP.",
- "payload": {
- "rotated": true,
- "orderId": "ord_8c21",
- "sessionId": "a1b2c3",
- "port": 9999,
- "protocol": "http",
- "rotatedAt": "2026-10-19T14:05:00.000Z",
- "nextAllowedAt": "2026-10-19T14:05:10.000Z",
- "linkId": "rlk_3f9a1c7e5b2d4a6c8e0f1a2b",
- "label": "Profile 12"
}, - "pagination": { }
}Buy and manage Premium ISP dedicated IPs through the API, paid from the wallet balance: ready pools by country and category, or city plans where you pick the city and, optionally, the carrier (ASN). Catalog with live stock, quote, purchase, order status with the proxy lines, renewal and IP replacement.
List Premium ISP pools
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Ready Premium ISP pools by country and site category: dedicated static IPs, unlimited bandwidth, 30-day plans. The supplier gives no stock count for pools; available tells whether a pool can be bought. fromPerIp is the lowest price per IP. Free.
Authorizations:
query Parameters
| country | string ISO 3166-1 alpha-2 filter, e.g. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/pools' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "enabled": true,
- "days": 30,
- "currency": "USD",
- "pools": [
- {
- "id": "premium-us-retail",
- "country": "US",
- "countryName": "United States",
- "category": "retail",
- "categoryName": "Retail",
- "name": "Premium United States Retail ISP",
- "description": "Dedicated static IPs optimized for retail websites, with unlimited bandwidth.",
- "days": 30,
- "minQuantity": 1,
- "maxQuantity": 100,
- "available": true,
- "features": {
- "dedicated": true,
- "unlimitedBandwidth": true,
- "udp": true,
- "maxSpeedGbps": 10,
- "cityChoice": false,
- "carrierChoice": false,
- "replacementWithin24hOnRequest": true,
- "subnetsOnRequest": true
}
}
]
}, - "pagination": { }
}List Premium ISP cities with stock
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
City plans of one type (city: City and carrier; fraud-score-0: every IP checked for a fraud score of 0 before delivery): the plan lengths on sale with their price per IP and quantity ranges, the carrier fee, and every country and city with the IPs in stock. Cached up to 2 minutes; the purchase reads the stock again. Free.
Authorizations:
query Parameters
| type | string Default: "city" Enum: "city" "fraud-score-0" |
| udp | string Default: "0" Enum: "0" "1"
|
| country | string ISO 3166-1 alpha-2 filter. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object City plans of one type: plan lengths with their price per IP, and the countries and cities with the IPs in stock. Served from a cache up to |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/cities' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "enabled": true,
- "type": "city",
- "udp": false,
- "maxAgeSeconds": 120,
- "types": [
- {
- "id": "city",
- "name": "City and carrier",
- "available": true
}, - {
- "id": "fraud-score-0",
- "name": "Fraud score 0",
- "available": true
}
], - "countries": [
- {
- "code": "US",
- "name": "United States",
- "stock": 1234,
- "cities": [
- {
- "location": "United States - New York City",
- "name": "New York City",
- "stock": 8
}
]
}
]
}, - "pagination": { }
}List the carriers (ASN) of a city
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Carriers with the IPs in stock in one city of the catalog. Pass one asn to the quote or the purchase to pin the carrier (a carrier fee per IP applies). Each new city is a live read, so this call has its own hourly cap per account (60). Free.
Authorizations:
query Parameters
| location required | string
|
| type | string Default: "city" Enum: "city" "fraud-score-0" |
| udp | string Default: "0" Enum: "0" "1" |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/cities/carriers?location=LOCATION' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "location": "United States - New York City",
- "type": "city",
- "udp": false,
- "maxAgeSeconds": 120,
- "carriers": [
- {
- "asn": 7922,
- "name": "Comcast",
- "stock": 5
}
]
}, - "pagination": { }
}Quote a Premium ISP selection
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Server-side price of a pool or city selection paid from the balance, with VAT (0% on balance) and whether your balance covers it. Nothing is reserved: the purchase checks stock and price again before charging. Free (300 quotes an hour per account).
Authorizations:
Request Body schema: application/jsonrequired
| product required | string Enum: "pool" "city" |
| quantity required | integer >= 1 Number of IPs, within the length's or pool's minQuantity/maxQuantity. |
| poolId | string Pool id from |
| type | string Default: "city" Enum: "city" "fraud-score-0" City plans only. |
| length | string Enum: "1_day" "7_days" "1_month" "2_months" "3_months" City plans only; the lengths on sale are listed by the catalog. |
| location | string City plans only: a |
| asn | integer or null Default: null City plans only: carrier ASN from |
| udp | boolean Default: false City plans only: UDP-capable IPs. |
| ispNameCheck | boolean Deprecated Default: false City plans only. Deprecated and currently ignored: this free beta is turned off, so the flag has no effect and no IPs are filtered — leave it out. (When on, it delivered only IPs an IP-lookup database lists under an internet provider.) |
| replacements | integer [ 0 .. 5 ] Default: 0 City plans only: IP replacements bought with the plan (they cannot be added later). |
| paymentMethod | string Default: "BALANCE" Value: "BALANCE" |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Server-side price of a selection. Nothing is reserved ( |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "product": "city",
- "type": "city",
- "length": "1_month",
- "location": "United States - New York City",
- "asn": 7922,
- "udp": false,
- "replacements": 2,
- "quantity": 10
}Response samples
- 200
- 400
- 401
- 403
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "product": "city",
- "type": "city",
- "length": "1_month",
- "days": 30,
- "location": "United States - New York City",
- "city": "New York City",
- "country": "United States",
- "asn": 7922,
- "carrierName": "Comcast",
- "udp": false,
- "quantity": 10,
- "replacements": 2,
- "vatRate": 0,
- "vat": 0,
- "currency": "USD",
- "paymentMethod": "BALANCE",
- "sufficientBalance": true,
- "reserved": false,
- "quotedAt": "2026-10-19T10:00:00.000Z"
}, - "pagination": { }
}List Premium ISP orders
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Your Premium ISP orders (pools and city plans), newest first, with their status. From our records only, no live reads. Renewals are not separate orders. Free.
Authorizations:
query Parameters
| limit | integer <= 100 Default: 50 |
| offset | integer Default: 0 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/orders' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "orders": [
- {
- "id": "ord_5f2a",
- "product": "city",
- "status": "active",
- "createdAt": "2026-10-19T10:00:00.000Z",
- "selection": {
- "type": "city",
- "length": "1_month",
- "location": "United States - New York City",
- "city": "New York City",
- "country": "United States",
- "asn": 7922,
- "carrierName": "Comcast",
- "udp": false,
- "replacements": 2
}, - "quantity": 10,
- "days": 30,
- "region": "premium-isp-city",
- "expiresAt": "2026-11-18T10:00:00.000Z",
- "daysRemaining": 30,
- "invoice": {
- "id": "inv_77c1",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}, - "replacements": {
- "bought": 2,
- "used": 0,
- "checking": 0,
- "left": 2
}
}
], - "pagination": {
- "total": 1,
- "limit": 50,
- "offset": 0,
- "hasMore": false
}
}, - "pagination": { }
}Buy Premium ISP IPs from the balance
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Buys a pool or city selection and charges the wallet balance (VAT 0%). The Idempotency-Key header is required: a retry with the same key never charges twice and answers with the same order. maxTotal (optional) refuses the purchase if the price went above it. The balance is checked before anything is created. Answers: 201 delivered; 202 paid and being prepared (poll GET /public/premium-isp/orders/{orderId}, see Location); 200 replayed: true for a key already used; 422 not delivered and refunded to the balance. Coupons are not accepted through the API. Whole /24 subnets and the 24-hour replacement of pool IPs are arranged with support. 20 purchases an hour per account.
Authorizations:
header Parameters
| Idempotency-Key required | string^[a-zA-Z0-9-]{16,128}$ Unique key per purchase or renewal, 16–128 letters, digits or dashes (a UUID works). Sending the same request again with the same key never charges twice: it answers with the order it already created. The same key with a different body answers 409 |
Request Body schema: application/jsonrequired
| product required | string Enum: "pool" "city" |
| quantity required | integer >= 1 Number of IPs, within the length's or pool's minQuantity/maxQuantity. |
| poolId | string Pool id from |
| type | string Default: "city" Enum: "city" "fraud-score-0" City plans only. |
| length | string Enum: "1_day" "7_days" "1_month" "2_months" "3_months" City plans only; the lengths on sale are listed by the catalog. |
| location | string City plans only: a |
| asn | integer or null Default: null City plans only: carrier ASN from |
| udp | boolean Default: false City plans only: UDP-capable IPs. |
| ispNameCheck | boolean Deprecated Default: false City plans only. Deprecated and currently ignored: this free beta is turned off, so the flag has no effect and no IPs are filtered — leave it out. (When on, it delivered only IPs an IP-lookup database lists under an internet provider.) |
| replacements | integer [ 0 .. 5 ] Default: 0 City plans only: IP replacements bought with the plan (they cannot be added later). |
| paymentMethod | string Default: "BALANCE" Value: "BALANCE" |
| maxTotal | number Highest total you accept, in USD. Above it: 409 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "product": "city",
- "type": "city",
- "length": "1_month",
- "location": "United States - New York City",
- "asn": 7922,
- "udp": false,
- "replacements": 2,
- "quantity": 10
}Response samples
- 200
- 201
- 202
- 400
- 401
- 402
- 403
- 409
- 422
- 429
- 503
{- "type": "response",
- "message": "This purchase was already received.",
- "payload": {
- "replayed": true,
- "order": {
- "id": "ord_5f2a",
- "product": "city",
- "status": "active",
- "createdAt": "2026-10-19T10:00:00.000Z",
- "selection": {
- "type": "city",
- "length": "1_month",
- "location": "United States - New York City",
- "city": "New York City",
- "country": "United States",
- "asn": 7922,
- "carrierName": "Comcast",
- "udp": false,
- "replacements": 2
}, - "quantity": 10,
- "days": 30,
- "region": "premium-isp-city",
- "expiresAt": "2026-11-18T10:00:00.000Z",
- "daysRemaining": 30,
- "invoice": {
- "id": "inv_77c1",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}, - "replacements": {
- "bought": 2,
- "used": 0,
- "checking": 0,
- "left": 2
}
}
}, - "pagination": { }
}Get a Premium ISP order and its proxy lines
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Status of one order. With include=lines it also returns the proxy lines (one per dedicated IP, with its own login), read live: 120 reads an hour per account. While the IPs are being prepared it answers 202 LINES_PENDING. Premium ISP IPs reach only ports 80 and 443. Pool plans also cannot open banking, payment or government sites; city plans have no site blocks. Free.
Authorizations:
path Parameters
| orderId required | string
|
query Parameters
| include | string Value: "lines" |
| protocol | string Default: "http" Enum: "http" "socks5" |
| format | string Default: "host:port:user:pass" Enum: "host:port:user:pass" "ip:port:user:pass" "user:pass@host:port" "http://user:pass@host:port" "socks5://user:pass@host:port" |
| quantity | integer >= 1 Return only the first N lines. |
| server | string City plans: a connection server id from |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/orders/ORDERID' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 202
- 400
- 401
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "order": {
- "id": "ord_5f2a",
- "product": "city",
- "status": "active",
- "createdAt": "2026-10-19T10:00:00.000Z",
- "selection": {
- "type": "city",
- "length": "1_month",
- "location": "United States - New York City",
- "city": "New York City",
- "country": "United States",
- "asn": 7922,
- "carrierName": "Comcast",
- "udp": false,
- "replacements": 2
}, - "quantity": 10,
- "days": 30,
- "region": "premium-isp-city",
- "expiresAt": "2026-11-18T10:00:00.000Z",
- "daysRemaining": 30,
- "invoice": {
- "id": "inv_77c1",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}, - "replacements": {
- "bought": 2,
- "used": 0,
- "checking": 0,
- "left": 2
}
}, - "lines": {
- "protocol": "http",
- "format": "host:port:user:pass",
- "proxies": [
- "203.0.113.7:8000:u_1a2b:p_3c4d"
], - "ipAddresses": [
- "203.0.113.7"
], - "expiresAt": "2026-11-18T10:00:00.000Z",
- "servers": [
- {
- "id": "auto",
- "label": "Auto (closest server)"
}, - {
- "id": "us-east",
- "label": "US East (Virginia)"
}, - {
- "id": "de",
- "label": "Frankfurt"
}, - {
- "id": "sg",
- "label": "Singapore"
}
], - "server": "auto"
}
}, - "pagination": { }
}Quote a Premium ISP renewal
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Price of renewing the plan for its own term with the same IPs, paid from the balance (VAT 0%). IP replacements are not renewed; the carrier fee is, when the plan has a carrier. Free.
Authorizations:
path Parameters
| orderId required | string
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/orders/ORDERID/renewal' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "days": 30,
- "quantity": 10,
- "vatRate": 0,
- "vat": 0,
- "currency": "USD",
- "paymentMethod": "BALANCE",
- "currentExpiry": "2026-11-18T10:00:00.000Z",
- "sufficientBalance": true
}, - "pagination": { }
}Renew a Premium ISP plan from the balance
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Extends the plan by its own term with the same IPs and charges the balance. Idempotency-Key is required. 202 means the renewal is being verified: do not send it again, it completes or is refunded automatically. 20 renewals an hour per account.
Authorizations:
path Parameters
| orderId required | string
|
header Parameters
| Idempotency-Key required | string^[a-zA-Z0-9-]{16,128}$ Unique key per purchase or renewal, 16–128 letters, digits or dashes (a UUID works). Sending the same request again with the same key never charges twice: it answers with the order it already created. The same key with a different body answers 409 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X POST 'https://api.quanticdata.io/v1/public/premium-isp/orders/ORDERID/renewal' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 202
- 400
- 401
- 402
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "renewed": true,
- "daysAdded": 30,
- "newExpiry": "2026-12-18T10:00:00.000Z"
}, - "pagination": { }
}IP replacements of a city plan
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Replacements bought with a city plan: used, being confirmed and left. Pools have no API replacements (their 24-hour replacement goes through support). Free.
Authorizations:
path Parameters
| orderId required | string
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/premium-isp/orders/ORDERID/replacements' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 404
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "bought": 2,
- "used": 0,
- "checking": 0,
- "left": 2
}, - "pagination": { }
}Replace one IP of a city plan
Price: No charge. Prices come from the catalog (GET /public/premium-isp/cities, GET /public/premium-isp/pools) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Swaps one IP of the plan for a new one in the same city, using one of the replacements bought with the plan. 202 means the new IP is being prepared: it counts as used, do not send it again. A 502 means nothing was used. 30 replacements an hour per account.
Authorizations:
path Parameters
| orderId required | string
|
Request Body schema: application/jsonrequired
| ip required | string One of the plan's exit IPs ( |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "ip": "203.0.113.7"
}Response samples
- 200
- 202
- 400
- 401
- 403
- 404
- 409
- 429
- 502
- 503
{- "type": "response",
- "message": "IP replaced.",
- "payload": {
- "pending": false,
- "oldIp": "203.0.113.7",
- "newIp": "203.0.113.42",
- "bought": 2,
- "used": 1,
- "checking": 0,
- "left": 1
}, - "pagination": { }
}Buy IPv6 speed plans through the API, paid from the wallet balance: traffic is not metered, the port speed is the cap. The grid of speeds (Mbps) and terms (1, 7 or 30 days) with the price of every cell, a quote, the purchase with an Idempotency-Key, order status. The endpoint strings of a bought plan come from POST /public/proxies/generate with the order id; per-GB IPv6 packs stay in GET /public/plans and POST /public/purchase. 1000 Mbps is a special plan sold on request (dashboard, Plans → IPv6 → Contact us).
List IPv6 speed plans
Price: No charge. Prices come from the grid (GET /public/ipv6/plans) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%. 1000 Mbps has no price: it is sold on request from the dashboard.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The grid of IPv6 speed plans on sale: every speed (Mbps) with the terms (1, 7 or 30 days) sold for it and the price of each cell, in USD, paid from the balance with 0% VAT. Traffic is not metered for the whole term; the port speed is the cap. from is the cheapest cell; onRequest is the 1000 Mbps plan, sold without a listed price from the dashboard. Rotating or static sessions, HTTP and SOCKS5 and country selection work as on the per-GB IPv6 packs (those stay in GET /public/plans). Free (300 reads an hour per account).
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object The IPv6 speed plans on sale right now: one entry per speed with the terms sold for it and the price of each cell. A speed missing a term is simply not sold for that term. |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/ipv6/plans' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 403
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "currency": "USD",
- "paymentMethod": "BALANCE",
- "vatRate": 0,
- "terms": [
- 1,
- 7,
- 30
], - "speeds": [
- {
- "speedMbps": 30,
- "terms": [
- {
- "days": 1,
- "planName": "IPv6 Unlimited · 30 Mbps · 1 day"
}, - {
- "days": 7,
- "planName": "IPv6 Unlimited · 30 Mbps · 7 days"
}, - {
- "days": 30,
- "planName": "IPv6 Unlimited · 30 Mbps · 30 days"
}
]
}, - {
- "speedMbps": 60,
- "terms": [
- {
- "days": 1,
- "planName": "IPv6 Unlimited · 60 Mbps · 1 day"
}, - {
- "days": 7,
- "planName": "IPv6 Unlimited · 60 Mbps · 7 days"
}, - {
- "days": 30,
- "planName": "IPv6 Unlimited · 60 Mbps · 30 days"
}
]
}, - {
- "speedMbps": 120,
- "terms": [
- {
- "days": 1,
- "planName": "IPv6 Unlimited · 120 Mbps · 1 day"
}, - {
- "days": 7,
- "planName": "IPv6 Unlimited · 120 Mbps · 7 days"
}, - {
- "days": 30,
- "planName": "IPv6 Unlimited · 120 Mbps · 30 days"
}
]
}, - {
- "speedMbps": 200,
- "terms": [
- {
- "days": 1,
- "planName": "IPv6 Unlimited · 200 Mbps · 1 day"
}, - {
- "days": 7,
- "planName": "IPv6 Unlimited · 200 Mbps · 7 days"
}, - {
- "days": 30,
- "planName": "IPv6 Unlimited · 200 Mbps · 30 days"
}
]
}
], - "from": {
- "speedMbps": 30,
- "days": 1
}, - "onRequest": {
- "speedMbps": 1000,
- "price": null,
- "availability": "contact",
- "how": "Ask for it in the dashboard: Plans → IPv6 → 1000 Mbps → Contact us. We reply by e-mail with the price."
}
}, - "pagination": { }
}Quote an IPv6 speed plan
Price: No charge. Prices come from the grid (GET /public/ipv6/plans) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%. 1000 Mbps has no price: it is sold on request from the dashboard.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Server-side price of one speed × term cell paid from the balance, with VAT (0% on balance) and whether your balance covers it. Nothing is reserved: the purchase reads the grid again before charging. A speed or term that is not sold answers 409 with the cells that are; 1000 Mbps answers CONTACT_REQUIRED. Free (300 quotes an hour per account).
Authorizations:
Request Body schema: application/jsonrequired
| speedMbps required | integer A speed of the grid ( |
| days required | integer Enum: 1 7 30 The term. Traffic is not metered for the whole term. |
| paymentMethod | string Default: "BALANCE" Value: "BALANCE" |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object Server-side price of one cell. Nothing is reserved. |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "speedMbps": 200,
- "days": 7
}Response samples
- 200
- 400
- 401
- 403
- 409
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "speedMbps": 200,
- "days": 7,
- "planName": "IPv6 Unlimited · 200 Mbps · 7 days",
- "trafficMetered": false,
- "vatRate": 0,
- "vat": 0,
- "currency": "USD",
- "paymentMethod": "BALANCE",
- "sufficientBalance": true,
- "reserved": false,
- "quotedAt": "2026-10-20T09:00:00.000Z"
}, - "pagination": { }
}List IPv6 speed orders
Price: No charge. Prices come from the grid (GET /public/ipv6/plans) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%. 1000 Mbps has no price: it is sold on request from the dashboard.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Status of the account's IPv6 speed orders, newest first, from our records only: dashboard and API purchases alike (channel). Per-GB IPv6 packs are not here: they are plans in GET /public/proxies. Free (120 reads an hour per account).
Authorizations:
query Parameters
| limit | integer [ 1 .. 100 ] Default: 50 |
| offset | integer >= 0 Default: 0 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/ipv6/orders' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 403
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "orders": [
- {
- "id": "ord_7a1c",
- "product": "ipv6-speed",
- "status": "active",
- "createdAt": "2026-10-20T09:00:00.000Z",
- "speedMbps": 200,
- "days": 7,
- "planName": "IPv6 Unlimited · 200 Mbps · 7 days",
- "trafficMetered": false,
- "expiresAt": "2026-10-27T09:00:00.000Z",
- "daysRemaining": 7,
- "channel": "api",
- "invoice": {
- "id": "inv_3b9e",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}
}
], - "pagination": {
- "total": 1,
- "limit": 50,
- "offset": 0,
- "hasMore": false
}
}, - "pagination": { }
}Buy an IPv6 speed plan
Price: No charge. Prices come from the grid (GET /public/ipv6/plans) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%. 1000 Mbps has no price: it is sold on request from the dashboard.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Buy one speed × term cell from the wallet balance. Send a unique Idempotency-Key with every purchase: the same key again answers with the order already created, never a second charge. The grid is read again at purchase time; maxTotal lets you refuse a price above what you quoted (409 PRICE_CHANGED, nothing charged). Answers: 201 delivered (the plan is active; generate the endpoint strings with POST /public/proxies/generate and the order id), 200 replayed for a key already paid, 422 not delivered and refunded to the balance. Keyless and pay-per-call access cannot buy; keys created by a connected app cannot spend. 20 purchases an hour per account.
Authorizations:
header Parameters
| Idempotency-Key required | string^[a-zA-Z0-9-]{16,128}$ Unique key per purchase or renewal, 16–128 letters, digits or dashes (a UUID works). Sending the same request again with the same key never charges twice: it answers with the order it already created. The same key with a different body answers 409 |
Request Body schema: application/jsonrequired
| speedMbps required | integer A speed of the grid ( |
| days required | integer Enum: 1 7 30 The term. Traffic is not metered for the whole term. |
| paymentMethod | string Default: "BALANCE" Value: "BALANCE" |
| maxTotal | number Refuse the purchase if the total is above this amount (USD). Nothing is charged then. |
| idempotencyKey | string^[a-zA-Z0-9-]{16,128}$ Alternative to the header. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "speedMbps": 200,
- "days": 7,
- "maxTotal": 150
}Response samples
- 200
- 201
- 400
- 401
- 402
- 403
- 409
- 422
- 429
- 503
{- "type": "response",
- "message": "This purchase was already received.",
- "payload": {
- "replayed": true,
- "order": {
- "id": "ord_7a1c",
- "product": "ipv6-speed",
- "status": "active",
- "createdAt": "2026-10-20T09:00:00.000Z",
- "speedMbps": 200,
- "days": 7,
- "planName": "IPv6 Unlimited · 200 Mbps · 7 days",
- "trafficMetered": false,
- "expiresAt": "2026-10-27T09:00:00.000Z",
- "daysRemaining": 7,
- "channel": "api",
- "invoice": {
- "id": "inv_3b9e",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}
}
}, - "pagination": { }
}Get an IPv6 speed order
Price: No charge. Prices come from the grid (GET /public/ipv6/plans) or from a quote, in USD, and are charged to the wallet balance. VAT on balance payments is 0%. 1000 Mbps has no price: it is sold on request from the dashboard.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
One IPv6 speed order of this account: status, speed, term, expiry and invoice, from our records. The endpoint strings come from POST /public/proxies/generate with this order id (rotating, sticky or static sessions, country selection). 404 for an order of another account or of another product. Free (120 reads an hour per account).
Authorizations:
path Parameters
| orderId required | string
|
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/ipv6/orders/ORDERID' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 403
- 404
- 429
- 503
{- "type": "response",
- "message": "Success",
- "payload": {
- "order": {
- "id": "ord_7a1c",
- "product": "ipv6-speed",
- "status": "active",
- "createdAt": "2026-10-20T09:00:00.000Z",
- "speedMbps": 200,
- "days": 7,
- "planName": "IPv6 Unlimited · 200 Mbps · 7 days",
- "trafficMetered": false,
- "expiresAt": "2026-10-27T09:00:00.000Z",
- "daysRemaining": 7,
- "channel": "api",
- "invoice": {
- "id": "inv_3b9e",
- "vat": 0,
- "vatRate": 0,
- "paid": true,
- "status": "PAID",
- "refunded": false
}
}
}, - "pagination": { }
}Buy proxy plans from the wallet balance and read your orders, so a script or an agent can go from API key to working proxies without the dashboard: GET /public/plans → POST /public/purchase → POST /public/proxies/generate with the order id (step by step in the guide Buy and use proxies via the API). Purchases are paid from the balance only, with 0% VAT; the balance is topped up in the dashboard. The plans listed here have a fixed size (GB and days). Products you configure at checkout, such as ISP proxies or unlimited-bandwidth plans, are bought in the dashboard, and Premium ISP has its own endpoints (see Premium ISP). Buying a plan again creates a separate order with new credentials: adding GB to an existing plan or renewing it is done in the dashboard.
List the plans you can buy
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Active plans with their size, duration and list price (amount, USD), cheapest first, also grouped by planType in groupedPlans. planTypes describes every plan type the API knows, including types that have no plan on sale. Use a plan's id as planId in POST /public/purchase. Products you configure at checkout (ISP proxies, unlimited-bandwidth plans) are not listed: they are bought in the dashboard, Premium ISP through its own endpoints. Free.
Authorizations:
query Parameters
| planType | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" Example: planType=residentialpremium Only plans of this type. An unknown value returns an empty list. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/plans?planType=residentialpremium' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "plans": [
- {
- "id": "pln_3e7a",
- "name": "Residential - Quark (5GB)",
- "planType": "residentialpremium",
- "planTypeName": "Residential Premium",
- "bandwidth": 5,
- "bandwidthGB": 5,
- "isUnlimited": false,
- "duration": 90,
- "durationDays": 90,
- "ips": 0,
- "whitelistSlots": 0,
- "region": "Global",
- "speed": 0,
- "highConcurrency": false,
- "highPriority": false
}
], - "groupedPlans": {
- "residentialpremium": [
- {
- "id": "pln_3e7a",
- "name": "Residential - Quark (5GB)",
- "planType": "residentialpremium",
- "planTypeName": "Residential Premium",
- "bandwidth": 5,
- "bandwidthGB": 5,
- "isUnlimited": false,
- "duration": 90,
- "durationDays": 90,
- "ips": 0,
- "whitelistSlots": 0,
- "region": "Global",
- "speed": 0,
- "highConcurrency": false,
- "highPriority": false
}
]
}, - "planTypes": [
- {
- "key": "residentialpremium",
- "name": "Residential Premium",
- "description": "Residential premium proxies - Premium quality with high success rate",
- "features": [
- "Premium residential IPs",
- "Higher success rate",
- "Fast speeds",
- "Geo-targeting available"
]
}
], - "total": 1
}, - "pagination": { }
}Buy a plan from the balance
Price: No charge. The call itself is free; the plan costs its amount from GET /public/plans (less the coupon, if any), charged to the wallet balance in USD with 0% VAT.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Buys one plan from GET /public/plans, charges the wallet balance (0% VAT) and activates the plan in the same call. The answer carries the order, the invoice and the plan's credentials; pass order.id as orderId to POST /public/proxies/generate. The balance is checked before anything is created: a balance that does not cover the total answers 400 Insufficient balance and nothing is charged. If the plan cannot be activated after the charge, the amount goes back to the balance and the call answers 422 NOT_DELIVERED_REFUNDED: you have not been charged and can buy again. There is no idempotency key on this endpoint: do not resend a purchase that timed out, read GET /public/orders first. A coupon is valid once per account, on the brand that issued it. A payment that fails leaves an unpaid invoice; ten unpaid invoices in 24 hours block new purchases (429 TOO_MANY_UNPAID_INVOICES). Unknown body fields are refused. Requires your own API key.
Authorizations:
Request Body schema: application/jsonrequired
| planId required | string
|
| coupon | string or null Coupon code (optional; empty string or null = none). |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- Payload
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
{- "planId": "pln_3e7a"
}Response samples
- 200
- 400
- 401
- 403
- 404
- 409
- 422
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "order": {
- "id": "ord_8c21",
- "planId": "pln_3e7a",
- "planName": "Residential - Quark (5GB)",
- "createdAt": "2026-10-19T10:00:00.000Z"
}, - "invoice": {
- "id": "inv_4b90",
- "vat": 0,
- "status": "PAID",
- "paid": true
}, - "proxy": {
- "id": "prx_1",
- "orderId": "ord_8c21",
- "username": "user_8c21",
- "password": "p4ssw0rd",
- "proxyType": "RESIDENTIAL",
- "region": "",
- "bandwidth": 5,
- "bandwidthLeft": 5,
- "noOfIps": 0,
- "noOfWhitelistedIps": 1,
- "speed": 0,
- "autoRenewDays": 90,
- "highConcurrency": false,
- "highPriority": false,
- "autoRenew": false,
- "expiry": "2027-01-17T10:00:00.000Z",
- "autoRenewLastAt": null,
- "gbReclaimedAt": null,
- "createdAt": "2026-10-19T10:00:00.000Z",
- "updatedAt": "2026-10-19T10:00:00.000Z",
- "whitelist_ip": [ ]
}
}, - "pagination": { }
}List your orders
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Every order of the account, newest first, with the plan, the proxy credentials and the invoices: use it to find an order after a purchase that timed out, to check what was charged, or to get the orderId of an older plan. For the live state of a plan (bandwidth used, days left) use GET /public/proxies. Plans disabled by support are not listed. Free.
Authorizations:
query Parameters
| limit | integer <= 100 Default: 50 |
| offset | integer Default: 0 |
| type | string Enum: "PROXY" "TOPUP" Only proxy plans ( |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/orders' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "orders": [
- {
- "id": "ord_8c21",
- "type": "PROXY",
- "createdAt": "2026-10-19T10:00:00.000Z",
- "plan": {
- "id": "pln_3e7a",
- "name": "Residential - Quark (5GB)",
- "planType": "residentialpremium",
- "planTypeName": "Residential Premium",
- "bandwidth": 5,
- "bandwidthGB": 5,
- "duration": 90,
- "ips": 0,
- "region": "Global"
}, - "proxy": {
- "id": "prx_1",
- "username": "user_8c21",
- "password": "p4ssw0rd",
- "planType": "residentialpremium",
- "planTypeName": "Residential Premium",
- "bandwidth": 5,
- "bandwidthGB": 5,
- "bandwidthLeft": 3.2,
- "bandwidthLeftGB": 3.2,
- "isUnlimited": false,
- "expiry": "2027-01-17T10:00:00.000Z",
- "isActive": true,
- "ips": 0,
- "whitelistedIPs": [ ],
- "region": "Global"
}, - "invoices": [
- {
- "id": "inv_4b90",
- "status": "PAID",
- "paid": true,
- "paidAt": "2026-10-19T10:00:01.000Z",
- "createdAt": "2026-10-19T10:00:00.000Z"
}
]
}
], - "pagination": {
- "total": 1,
- "limit": 50,
- "offset": 0,
- "hasMore": false
}
}, - "pagination": { }
}Get the wallet balance
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The wallet balance in USD, the one POST /public/purchase and the Data API draw from, and the total spent on proxy plans. Read it before a purchase: a balance below the plan's amount answers 400 Insufficient balance. Top-ups are made in the dashboard. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/balance' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "balance": 42.5,
- "balanceUSD": 42.5,
- "totalSpent": 120,
- "totalSpentUSD": 120
}, - "pagination": { }
}The values POST /public/proxies/generate accepts as country, state (alias region), city, isp and asn. Which endpoint to read depends on the plan type:
| Plan type | Location values |
|---|---|
residentialpremium |
GET /public/generator/residential-premium/targeting-options: the whole tree (country, region, city, ISP) in one call |
mobile_v2 |
GET /public/generator/mobile/targeting-options: the whole tree (country, region, city, carrier) in one call |
residentialbasic, datacentertraffic |
GET /public/geo/countries, /geo/states, /geo/cities and /geo/asns, one level per call (needs one of these plans on the account) |
ipv6 |
GET /public/geo/countries?planType=ipv6 |
datacenter (static gateways) |
GET /public/generator/datacenter/targeting-options: the gateway hosts and ports |
Locations follow the network and change over time: read them when you build a request instead of keeping a copy for months. All free.
List countries for a plan type
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Countries you can target with a plan type; send code as country to POST /public/proxies/generate. Residential Basic and traffic-based Datacenter return the live list of the network when the account has one of these plans, otherwise the general country list. Residential Premium and Mobile read the live tree. IPv6 returns its own list, including mix (any country). ISP, Premium ISP and static-gateway Datacenter plans have their location fixed at purchase: for them this is the general country list, not a targeting option. Free.
Authorizations:
query Parameters
| planType required | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" Example: planType=residentialbasic Plan type whose countries you want. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/geo/countries?planType=residentialbasic' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "countries": [
- {
- "code": "us",
- "name": "United States"
}, - {
- "code": "de",
- "name": "Germany"
}
], - "planType": "residentialbasic"
}, - "pagination": { }
}List states or regions of a country
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
States or regions of one country for a plan type; send code as state (alias region) to POST /public/proxies/generate. Available for Residential Basic and traffic-based Datacenter (live list, needs one of these plans on the account), Residential Premium and Mobile. Other plan types answer an empty list. For Residential Premium and Mobile V2 the targeting options return every level in one call. Free.
Authorizations:
query Parameters
| planType required | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" Example: planType=residentialpremium Plan type. |
| country required | string Example: country=AL Country code, either case. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/geo/states?planType=residentialpremium&country=AL' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "states": [
- {
- "code": "durres",
- "state_code": "durres",
- "name": "Durres",
- "state": "Durres"
}
], - "country": "AL",
- "planType": "residentialpremium"
}, - "pagination": { }
}List cities of a country or state
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Cities of one country, optionally narrowed to a state, for a plan type; send the city as city to POST /public/proxies/generate (see GeoCity for which field). Residential Premium lists cities per state: pass state, or the list is empty. Residential Basic and traffic-based Datacenter need one of these plans on the account. Other plan types answer an empty list. Free.
Authorizations:
query Parameters
| planType required | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" Example: planType=residentialpremium Plan type. |
| country required | string Example: country=AL Country code, either case. |
| state | string Example: state=durres State |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/geo/cities?planType=residentialpremium&country=AL&state=durres' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "cities": [
- {
- "code": "durres",
- "name": "Durres"
}
], - "country": "AL",
- "state": "durres",
- "planType": "residentialpremium"
}, - "pagination": { }
}List ASNs for Residential Basic and Datacenter
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Networks (autonomous systems) you can target with Residential Basic and traffic-based Datacenter plans, for one country or all of them; send asn as asn to POST /public/proxies/generate together with a country (ASN targeting needs a country). Needs one of these plans on the account. Other plan types answer 400. Free.
Authorizations:
query Parameters
| planType required | string Enum: "residentialbasic" "residentialpremium" "resiprivate" "isp" "isppremium" "datacenter" "datacentertraffic" "ipv6" "mobile" "mobile_v2" Example: planType=residentialbasic
|
| country | string Example: country=US Country code; omit for every country. |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/geo/asns?planType=residentialbasic&country=US' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 404
- 429
- 500
{- "type": "response",
- "message": "success",
- "payload": {
- "asns": [
- {
- "asn": "7922",
- "name": "Comcast Cable Communications, LLC"
}
], - "country": "US",
- "planType": "residentialbasic"
}, - "pagination": { }
}Residential Premium location tree (geo)
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The whole Residential Premium location tree in one call: countries, regions, cities and the ISPs available at each level. The tree keys are the country, state and city values and isps[].code the isp value of POST /public/proxies/generate; countries is the flat country list. When the tree cannot be read the call still answers 200, with success: false and an empty data: retry. Same answer as GET /public/generator/residential-premium/targeting-options. Free.
Authorizations:
query Parameters
| planType | string Value: "residentialpremium" Optional; only |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/geo/locations' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 400
- 401
- 429
{- "type": "response",
- "message": "Location data retrieved successfully",
- "payload": {
- "success": true,
- "message": "Location data retrieved successfully",
- "data": {
- "al": {
- "country_name": "Albania",
- "regions": {
- "durres": {
- "region_name": "Durres",
- "cities": {
- "durres": {
- "city_name": "Durres",
- "isps": [
- {
- "code": "abissnet_sh.a.",
- "name": "Abissnet Sh.A."
}
]
}
}
}
}
}
}, - "countries": [
- {
- "code": "al",
- "name": "Albania"
}
]
}, - "pagination": { }
}Residential Premium targeting options
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The whole Residential Premium location tree in one call: countries, regions, cities and the ISPs available at each level. The tree keys are the country, state and city values and isps[].code the isp value of POST /public/proxies/generate; countries is the flat country list. When the tree cannot be read the call still answers 200, with success: false and an empty data: retry. The MCP tool proxy_locations reads it. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/generator/residential-premium/targeting-options' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
{- "type": "response",
- "message": "Location data retrieved successfully",
- "payload": {
- "success": true,
- "message": "Location data retrieved successfully",
- "data": {
- "al": {
- "country_name": "Albania",
- "regions": {
- "durres": {
- "region_name": "Durres",
- "cities": {
- "durres": {
- "city_name": "Durres",
- "isps": [
- {
- "code": "abissnet_sh.a.",
- "name": "Abissnet Sh.A."
}
]
}
}
}
}
}
}, - "countries": [
- {
- "code": "al",
- "name": "Albania"
}
]
}, - "pagination": { }
}Mobile targeting options
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The whole Mobile location tree in one call: countries, regions, cities and the carriers available in each city. The tree keys are the country, state (alias region) and city values and isps[].code the isp value of POST /public/proxies/generate for Mobile V2 plans (planType: mobile_v2); the same values serve the Mobile V2 whitelist options. A country without carriers in the tree is targeted at country, region or city level. The MCP tool proxy_locations reads it. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/generator/mobile/targeting-options' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
- 502
{- "type": "response",
- "message": "Mobile targeting options retrieved successfully",
- "payload": {
- "success": true,
- "message": "Use the tree keys as values for POST /api/v1/public/proxies/generate: country (top-level key), region (regions key), city (cities key), isp (isps[].code).",
- "data": {
- "us": {
- "country_name": "United States",
- "regions": {
- "ohio": {
- "region_name": "Ohio",
- "cities": {
- "cincinnati": {
- "city_name": "Cincinnati",
- "zipcodes": [ ],
- "isps": [
- {
- "code": "t_mobile_usa",
- "name": "T-Mobile Usa"
}, - {
- "code": "verizon_wireless",
- "name": "Verizon Wireless"
}
]
}
}
}
}
}
}, - "countries": [
- {
- "code": "us",
- "name": "United States"
}
]
}, - "pagination": { }
}Datacenter gateway locations
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
The gateways of the static-gateway Datacenter plans (planType: datacenter): one host per country with its HTTP and SOCKS5 port. POST /public/proxies/generate returns one line per gateway for these plans; with the plan's username and password you can also build the lines yourself (username:password@host:port). Traffic-based Datacenter plans (datacentertraffic) are targeted by country, state, city and ASN instead: see GET /public/geo/countries. The MCP tool proxy_locations reads it. Free.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/public/generator/datacenter/targeting-options' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
{- "type": "response",
- "message": "Datacenter (static gateways) targeting options retrieved successfully",
- "payload": {
- "success": true,
- "message": "Available locations for Datacenter (static gateways) plans. Use host + portHttp (9999) or portSocks5 (10000) with your proxy credentials.",
- "locations": [
- {
- "code": "us",
- "name": "United States",
- "host": "datacenter-us.quantumproxies.io",
- "portHttp": 9999,
- "portSocks5": 10000
}, - {
- "code": "ca",
- "name": "Canada",
- "host": "datacenter-ca.quantumproxies.io",
- "portHttp": 9999,
- "portSocks5": 10000
}, - {
- "code": "de",
- "name": "Germany",
- "host": "datacenter-de.quantumproxies.io",
- "portHttp": 9999,
- "portSocks5": 10000
}, - {
- "code": "gb",
- "name": "United Kingdom",
- "host": "datacenter-gb.quantumproxies.io",
- "portHttp": 9999,
- "portSocks5": 10000
}, - {
- "code": "nl",
- "name": "Netherlands",
- "host": "datacenter-nl.quantumproxies.io",
- "portHttp": 9999,
- "portSocks5": 10000
}
]
}, - "pagination": { }
}Per-day usage and cost
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Request counts (total and per query type), proxy bandwidth, AI token cost and billed vs free-tier spend per UTC day for the calling key's account, read from the daily aggregation. Free; not subject to the Data API kill switch.
Authorizations:
query Parameters
| days | integer [ 1 .. 90 ] Default: 30 |
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/usage' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
{- "type": "response",
- "message": "Scraper usage",
- "payload": {
- "days": [
- {
- "date": "2026-10-06",
- "requests": 143,
- "by_type": {
- "extract": 120,
- "google": 20,
- "map": 3
}, - "proxy_kb": 61230,
- "ai_cost_usd": 0,
- "billed_usd": 0,
- "free_usd": 0.0375
}
], - "totals": {
- "requests": 143,
- "by_type": {
- "extract": 120,
- "google": 20,
- "map": 3
}, - "proxy_kb": 61230,
- "billed_usd": 0,
- "free_usd": 0.0375
}, - "period_days": 30
}, - "pagination": { }
}Billing status and your price list
Price: No charge.
Rate limit: Per API key, by tier (see Rate limits and tiers).
Try it in the Playground · Markdown for this group
Current price list with your tier's discount applied (keyed like pricing.json), monthly free allowance and what is left of it, wallet balance, active tier, billing mode and the per-minute limits each mode carries. Lets a client or an agent budget its calls without a dashboard round-trip. Free; not subject to the Data API kill switch.
Authorizations:
Responses
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/scraper/billing' \ -H 'Authorization: Bearer qd_live_YOUR_API_KEY'
Response samples
- 200
- 401
- 429
{- "type": "response",
- "message": "Billing status",
- "payload": {
- "billing_enabled": true,
- "billed": true,
- "balance": 12.5,
- "tier": {
- "key": "payg",
- "name": "Pay as you go",
- "discount_pct": 0,
- "rate_limit_per_min": 20
}, - "billing_mode": {
- "preference": "free_first",
- "effective": "free_first",
- "available": true,
- "free_first_rate_limit_per_min": 20,
- "balance_rate_limit_per_min": 300,
- "effective_rate_limit_per_min": 20
}, - "free_monthly_usd": 2,
- "free_remaining_usd": 1.62,
- "ai_token_markup": 2,
- "prices_usd": {
- "extract": 0.0015,
- "extract_render": 0.0025,
- "serp": 0.0009,
- "serp_render": 0.002,
- "map": 0.003,
- "seo_audit": 0.003,
- "crawl_page": 0.0003,
- "batch_url": 0.0004,
- "collector_result": 0.002
}
}, - "pagination": { }
}No-key MCP trial settings
Price: No charge.
Rate limit: No rate limit.
Try it in the Playground · Markdown for this group
What the keyless trial of the hosted MCP endpoint allows right now for a brand: whether it is on, calls per client address per UTC day, calls across all addresses per day, and which tools it may run. Read by the hosted MCP servers once a minute; nothing secret in it, so it needs no API key and is cacheable for 60 s. The brand comes from ?brand= or, failing that, from the request host.
query Parameters
| brand | string Enum: "QP" "QD" QP = QuantumProxies, QD = QuanticData. Defaults to the brand of the host you call. |
Responses
| Cache-Control | string
|
Response Schema: application/json
| type required | string Value: "response" |
| message required | string |
required | object |
| pagination | object Empty |
Request samples
- curl
- Python (requests)
- Node (fetch)
- PHP (curl)
curl -X GET 'https://api.quanticdata.io/v1/mcp/trial-config'
Response samples
- 200
{- "type": "response",
- "message": "ok",
- "payload": {
- "brand": "QD",
- "enabled": true,
- "perIpPerDay": 5,
- "perDay": 300,
- "tools": [
- "scrape",
- "search",
- "search_and_read",
- "map",
- "seo_audit",
- "list_collectors",
- "collector_run_status",
- "proxy_locations"
]
}
}