# AI — QuantumProxies.io API

> AI endpoints of the QuantumProxies.io API with parameters, request and response examples in cURL, Python, Node.js and PHP. Part of https://quantumproxies.io/docs/index.md.

Base URL `https://api.quantumproxies.io/v1` · Auth `Authorization: Bearer qp_live_…` · HTML: https://quantumproxies.io/docs/ · OpenAPI: https://quantumproxies.io/docs/openapi.json · All endpoints: https://quantumproxies.io/docs/llms.txt · This file: https://quantumproxies.io/docs/ai.md

_Generated from openapi.json v2026-10-07 on 2026-10-07; prices and limits as of 2026-10-07_

## AI extraction

Natural-language agents that drive the scraper and return JSON.

### Natural-language scraping agent

`POST /scraper/ai`

**Price:** `ai_extract` $0.001 per call, max $1.50 per call · `extract` $0.0002 per call + $3/GB, max $0.02 per call · `serp` $0.0005 per call · `map` $0.0005 per call. ai_extract + steps × extract + searches × serp + mapped × map + tokens × ai_token_markup, capped at meters.ai_extract.capUsd. _(list of 2026-10-07)_  
**Rate limit:** Per API key, by tier (see Rate limits and tiers).  
[Try it in the Playground](https://app.quantumproxies.io/data-api/playground) · [Markdown for this group](https://quantumproxies.io/docs/ai.md)

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.

#### Request body (required)

`Content-Type: application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `task` | string | yes | Plain-English instruction, e.g. "get every product with its name and price from this page". |
| `url` | string | no | Starting URL, if the task does not already contain one. |

Example:

```json
{
  "task": "Get every plan and its monthly price",
  "url": "https://example.com/pricing"
}
```

#### Examples

**curl**

```bash
curl -X POST 'https://api.quantumproxies.io/v1/scraper/ai' \
  -H 'Authorization: Bearer qp_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":"Get every plan and its monthly price","url":"https://example.com/pricing"}'
```

**Python (requests)**

```python
import requests

r = requests.post(
    'https://api.quantumproxies.io/v1/scraper/ai',
    headers={"Authorization": "Bearer qp_live_YOUR_API_KEY"},
    json={
        "task": "Get every plan and its monthly price",
        "url": "https://example.com/pricing"
    },
    timeout=120,
)
data = r.json()
if data["type"] != "response":
    raise SystemExit(data["message"])
print(data["payload"])
```

**Node (fetch)**

```javascript
const res = await fetch("https://api.quantumproxies.io/v1/scraper/ai", {
  method: "POST",
  headers: {
    Authorization: "Bearer qp_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "task": "Get every plan and its monthly price",
    "url": "https://example.com/pricing"
  })
});
const data = await res.json();
if (data.type !== "response") throw new Error(data.message);
console.log(data.payload);
```

**PHP (curl)**

```php
<?php
$ch = curl_init('https://api.quantumproxies.io/v1/scraper/ai');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer qp_live_YOUR_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'task' => 'Get every plan and its monthly price',
    'url' => 'https://example.com/pricing'
  ]),
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if ($data['type'] !== 'response') { throw new RuntimeException($data['message']); }
print_r($data['payload']);
```

#### Responses

- `200` — Extraction finished.
- `400` — Missing task, or the agent reported a client-side problem (bad URL, page unusable).
- `401` — Missing, malformed, unknown, disabled or expired API key; or the account is not active.
- `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.
- `429` — Key rate limit (hourly window), plan per-minute budget, browser-render concurrency, or pool capacity. Back off on Retry-After.
- `500` — Agent failure or the AI agent is not configured on this instance. Never billed.
- `503` — The Data API group is switched off for non-admin keys (early-access kill switch).

Example `200` response:

```json
{
  "type": "response",
  "message": "AI extraction successful",
  "payload": {
    "data": {
      "plans": [
        {
          "name": "Starter",
          "price_usd": 9
        },
        {
          "name": "Growth",
          "price_usd": 29
        }
      ]
    },
    "steps": [
      {
        "url": "https://example.com/pricing",
        "status": 200,
        "engine": "tls"
      }
    ],
    "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": {}
}
```

Example `401`:

```json
{
  "type": "error",
  "message": "Missing or invalid Authorization header. Use: Authorization: Bearer qp_live_YOUR_API_KEY"
}
```

Example `402`:

```json
{
  "type": "error",
  "message": "Your free tier for this month is used up and your balance can't cover this call (estimated $0.002). Add pay-as-you-go credit or pick a plan — your API key stays the same: https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
  "payload": {
    "code": "INSUFFICIENT_FUNDS",
    "balance": 0,
    "free_remaining": 0,
    "estimated_cost": 0.002,
    "plans_url": "https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
    "billing_mode": "free_first"
  }
}
```

Example `429`:

```json
{
  "type": "error",
  "message": "Rate limit exceeded. Resets in 23 minutes.",
  "payload": {
    "rateLimit": 1200,
    "requestCount": 1200,
    "resetAt": "2026-10-07T15:00:00.000Z"
  }
}
```

Example `503`:

```json
{
  "type": "error",
  "message": "This API is temporarily unavailable while we finalize pricing. Contact support for early access."
}
```

Try it: https://app.quantumproxies.io/data-api/playground

### AI Places Finder

`POST /scraper/places-ai`

**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-07)_  
**Rate limit:** Per API key, by tier (see Rate limits and tiers).  
[Try it in the Playground](https://app.quantumproxies.io/data-api/playground) · [Markdown for this group](https://quantumproxies.io/docs/ai.md)

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.

#### Request body (required)

`Content-Type: application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `task` | string | yes |  |
| `country` | string | no | ISO country override for the proxy exit and `gl`. |
| `enrich` | boolean | no | Fill phone/website/hours/address from each business's knowledge panel. Default `true`. |
| `max_enrich` | number | no | Knowledge-panel lookups budget (cap 30). Default `15`. |

Example:

```json
{
  "task": "find every car repair shop in Naples",
  "country": "it",
  "max_enrich": 10
}
```

#### Examples

**curl**

```bash
curl -X POST 'https://api.quantumproxies.io/v1/scraper/places-ai' \
  -H 'Authorization: Bearer qp_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":"find every car repair shop in Naples","country":"it","max_enrich":10}'
```

**Python (requests)**

```python
import requests

r = requests.post(
    'https://api.quantumproxies.io/v1/scraper/places-ai',
    headers={"Authorization": "Bearer qp_live_YOUR_API_KEY"},
    json={
        "task": "find every car repair shop in Naples",
        "country": "it",
        "max_enrich": 10
    },
    timeout=120,
)
data = r.json()
if data["type"] != "response":
    raise SystemExit(data["message"])
print(data["payload"])
```

**Node (fetch)**

```javascript
const res = await fetch("https://api.quantumproxies.io/v1/scraper/places-ai", {
  method: "POST",
  headers: {
    Authorization: "Bearer qp_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "task": "find every car repair shop in Naples",
    "country": "it",
    "max_enrich": 10
  })
});
const data = await res.json();
if (data.type !== "response") throw new Error(data.message);
console.log(data.payload);
```

**PHP (curl)**

```php
<?php
$ch = curl_init('https://api.quantumproxies.io/v1/scraper/places-ai');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer qp_live_YOUR_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'task' => 'find every car repair shop in Naples',
    'country' => 'it',
    'max_enrich' => 10
  ]),
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if ($data['type'] !== 'response') { throw new RuntimeException($data['message']); }
print_r($data['payload']);
```

#### Responses

- `200` — Places found.
- `400` — Malformed input. `message` names the parameter and the rule it broke.
- `401` — Missing, malformed, unknown, disabled or expired API key; or the account is not active.
- `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.
- `429` — Key rate limit (hourly window), plan per-minute budget, browser-render concurrency, or pool capacity. Back off on Retry-After.
- `500` — Finder failure or not configured on this instance. Never billed.
- `503` — The Data API group is switched off for non-admin keys (early-access kill switch).

Example `200` response:

```json
{
  "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",
        "website": "https://example.it"
      }
    ],
    "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": {}
}
```

Example `400`:

```json
{
  "type": "error",
  "message": "Invalid format. Must be one of: markdown, html, text (or data_format markdown/screenshot, format raw)"
}
```

Example `401`:

```json
{
  "type": "error",
  "message": "Missing or invalid Authorization header. Use: Authorization: Bearer qp_live_YOUR_API_KEY"
}
```

Example `402`:

```json
{
  "type": "error",
  "message": "Your free tier for this month is used up and your balance can't cover this call (estimated $0.002). Add pay-as-you-go credit or pick a plan — your API key stays the same: https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
  "payload": {
    "code": "INSUFFICIENT_FUNDS",
    "balance": 0,
    "free_remaining": 0,
    "estimated_cost": 0.002,
    "plans_url": "https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
    "billing_mode": "free_first"
  }
}
```

Example `429`:

```json
{
  "type": "error",
  "message": "Rate limit exceeded. Resets in 23 minutes.",
  "payload": {
    "rateLimit": 1200,
    "requestCount": 1200,
    "resetAt": "2026-10-07T15:00:00.000Z"
  }
}
```

Example `503`:

```json
{
  "type": "error",
  "message": "This API is temporarily unavailable while we finalize pricing. Contact support for early access."
}
```

Try it: https://app.quantumproxies.io/data-api/playground

### AI Shopping Finder

`POST /scraper/shopping-ai`

**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-07)_  
**Rate limit:** Per API key, by tier (see Rate limits and tiers).  
[Try it in the Playground](https://app.quantumproxies.io/data-api/playground) · [Markdown for this group](https://quantumproxies.io/docs/ai.md)

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.

#### Request body (required)

`Content-Type: application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `task` | string | yes |  |
| `country` | string | no | ISO country override for the proxy exit, `gl` and currency. |

Example:

```json
{
  "task": "cheapest Nintendo Switch OLED",
  "country": "it"
}
```

#### Examples

**curl**

```bash
curl -X POST 'https://api.quantumproxies.io/v1/scraper/shopping-ai' \
  -H 'Authorization: Bearer qp_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":"cheapest Nintendo Switch OLED","country":"it"}'
```

**Python (requests)**

```python
import requests

r = requests.post(
    'https://api.quantumproxies.io/v1/scraper/shopping-ai',
    headers={"Authorization": "Bearer qp_live_YOUR_API_KEY"},
    json={
        "task": "cheapest Nintendo Switch OLED",
        "country": "it"
    },
    timeout=120,
)
data = r.json()
if data["type"] != "response":
    raise SystemExit(data["message"])
print(data["payload"])
```

**Node (fetch)**

```javascript
const res = await fetch("https://api.quantumproxies.io/v1/scraper/shopping-ai", {
  method: "POST",
  headers: {
    Authorization: "Bearer qp_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "task": "cheapest Nintendo Switch OLED",
    "country": "it"
  })
});
const data = await res.json();
if (data.type !== "response") throw new Error(data.message);
console.log(data.payload);
```

**PHP (curl)**

```php
<?php
$ch = curl_init('https://api.quantumproxies.io/v1/scraper/shopping-ai');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer qp_live_YOUR_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'task' => 'cheapest Nintendo Switch OLED',
    'country' => 'it'
  ]),
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if ($data['type'] !== 'response') { throw new RuntimeException($data['message']); }
print_r($data['payload']);
```

#### Responses

- `200` — Products found.
- `400` — Malformed input. `message` names the parameter and the rule it broke.
- `401` — Missing, malformed, unknown, disabled or expired API key; or the account is not active.
- `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.
- `429` — Key rate limit (hourly window), plan per-minute budget, browser-render concurrency, or pool capacity. Back off on Retry-After.
- `500` — Finder failure or not configured on this instance. Never billed.
- `503` — The Data API group is switched off for non-admin keys (early-access kill switch).

Example `200` response:

```json
{
  "type": "response",
  "message": "Shopping search successful",
  "payload": {
    "products": [
      {
        "title": "Nintendo Switch OLED Bianco",
        "price": "€ 299,00",
        "merchant": "Example Store",
        "link": "https://example.it/p/switch-oled"
      }
    ],
    "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": {}
}
```

Example `400`:

```json
{
  "type": "error",
  "message": "Invalid format. Must be one of: markdown, html, text (or data_format markdown/screenshot, format raw)"
}
```

Example `401`:

```json
{
  "type": "error",
  "message": "Missing or invalid Authorization header. Use: Authorization: Bearer qp_live_YOUR_API_KEY"
}
```

Example `402`:

```json
{
  "type": "error",
  "message": "Your free tier for this month is used up and your balance can't cover this call (estimated $0.002). Add pay-as-you-go credit or pick a plan — your API key stays the same: https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
  "payload": {
    "code": "INSUFFICIENT_FUNDS",
    "balance": 0,
    "free_remaining": 0,
    "estimated_cost": 0.002,
    "plans_url": "https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
    "billing_mode": "free_first"
  }
}
```

Example `429`:

```json
{
  "type": "error",
  "message": "Rate limit exceeded. Resets in 23 minutes.",
  "payload": {
    "rateLimit": 1200,
    "requestCount": 1200,
    "resetAt": "2026-10-07T15:00:00.000Z"
  }
}
```

Example `503`:

```json
{
  "type": "error",
  "message": "This API is temporarily unavailable while we finalize pricing. Contact support for early access."
}
```

Try it: https://app.quantumproxies.io/data-api/playground

## AI visibility

Can AI assistants read and cite a page?

### AI visibility audit

`POST /scraper/ai-visibility`

**Price:** `ai_visibility` $0.002 per call · `ai_visibility_citation` $0.01 per call · `serp` $0.0005 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-07)_  
**Rate limit:** Per API key, by tier (see Rate limits and tiers).  
[Try it in the Playground](https://app.quantumproxies.io/data-api/playground) · [Markdown for this group](https://quantumproxies.io/docs/ai.md)

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.

#### Request body (required)

`Content-Type: application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | string | yes |  |
| `queries` | array of string | no | Questions to ask the engines. Absent = on-page audit only. |
| `engines` | array of string: `perplexity`, `openai`, `anthropic`, `aio`, `copilot`, `deepseek` | no | Subset of engines for the citation panel; default all six. `deepseek` = our Google top-10 handed to DeepSeek (cheapest). |
| `competitors` | array of string | no | Domains to name explicitly in the share of voice. |
| `brand` | string | no | Name to look for in answer text ("mentioned"). |
| `country` | string | no | Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. `all` means no targeting. |
| `no_render` | boolean | no | Skip the rendered pass (cheaper). Alias `noRender`. Default `false`. |
| `no_bot_fetch` | boolean | no | Skip the extra request that identifies as an AI crawler. Alias `noBotFetch`. Default `false`. |
| `no_retrieval` | boolean | no | Skip the 2 retrievability SERPs (rank for the page's own H1 question, index status). Alias `noRetrieval`. Default `false`. |
| `offsite` | boolean | no | Also search the brand on YouTube, Reddit, Wikipedia, LinkedIn and review sites (5 SERPs). Default `false`. |

Example:

```json
{
  "url": "https://example.com/blog/how-to-choose-a-proxy",
  "queries": [
    "how do I choose a residential proxy provider?"
  ],
  "engines": [
    "perplexity",
    "aio"
  ],
  "brand": "Example"
}
```

#### Examples

**curl**

```bash
curl -X POST 'https://api.quantumproxies.io/v1/scraper/ai-visibility' \
  -H 'Authorization: Bearer qp_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/blog/how-to-choose-a-proxy","queries":["how do I choose a residential proxy provider?"],"engines":["perplexity","aio"],"brand":"Example"}'
```

**Python (requests)**

```python
import requests

r = requests.post(
    'https://api.quantumproxies.io/v1/scraper/ai-visibility',
    headers={"Authorization": "Bearer qp_live_YOUR_API_KEY"},
    json={
        "url": "https://example.com/blog/how-to-choose-a-proxy",
        "queries": [
            "how do I choose a residential proxy provider?"
        ],
        "engines": [
            "perplexity",
            "aio"
        ],
        "brand": "Example"
    },
    timeout=120,
)
data = r.json()
if data["type"] != "response":
    raise SystemExit(data["message"])
print(data["payload"])
```

**Node (fetch)**

```javascript
const res = await fetch("https://api.quantumproxies.io/v1/scraper/ai-visibility", {
  method: "POST",
  headers: {
    Authorization: "Bearer qp_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "url": "https://example.com/blog/how-to-choose-a-proxy",
    "queries": [
      "how do I choose a residential proxy provider?"
    ],
    "engines": [
      "perplexity",
      "aio"
    ],
    "brand": "Example"
  })
});
const data = await res.json();
if (data.type !== "response") throw new Error(data.message);
console.log(data.payload);
```

**PHP (curl)**

```php
<?php
$ch = curl_init('https://api.quantumproxies.io/v1/scraper/ai-visibility');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer qp_live_YOUR_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'url' => 'https://example.com/blog/how-to-choose-a-proxy',
    'queries' => ['how do I choose a residential proxy provider?'],
    'engines' => ['perplexity', 'aio'],
    'brand' => 'Example'
  ]),
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if ($data['type'] !== 'response') { throw new RuntimeException($data['message']); }
print_r($data['payload']);
```

#### Responses

- `200` — Audit finished. `billing` says how many citation calls and SERPs were charged.
- `400` — Malformed input. `message` names the parameter and the rule it broke.
- `401` — Missing, malformed, unknown, disabled or expired API key; or the account is not active.
- `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.
- `403` — No proxy pool is available to serve the call (no house plan and no residential/datacenter/IPv6 plan on the account).
- `429` — Key/plan rate limit, or the account's daily cap on external AI-engine calls (payload: limit, remaining, reset_at, requested).
- `500` — Our side: the scraper service is unavailable or the call timed out. Never billed.
- `503` — The Data API group is switched off for non-admin keys (early-access kill switch).

Example `200` response:

```json
{
  "type": "response",
  "message": "AI visibility audit successful",
  "payload": {
    "url": "https://example.com/blog/how-to-choose-a-proxy",
    "finalUrl": "https://example.com/blog/how-to-choose-a-proxy",
    "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,
      "robotsTxtUrl": "https://example.com/robots.txt",
      "blockedCritical": [],
      "sitemaps": [
        "https://example.com/sitemap.xml"
      ],
      "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": {}
}
```

Example `400`:

```json
{
  "type": "error",
  "message": "Invalid format. Must be one of: markdown, html, text (or data_format markdown/screenshot, format raw)"
}
```

Example `401`:

```json
{
  "type": "error",
  "message": "Missing or invalid Authorization header. Use: Authorization: Bearer qp_live_YOUR_API_KEY"
}
```

Example `402`:

```json
{
  "type": "error",
  "message": "Your free tier for this month is used up and your balance can't cover this call (estimated $0.002). Add pay-as-you-go credit or pick a plan — your API key stays the same: https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
  "payload": {
    "code": "INSUFFICIENT_FUNDS",
    "balance": 0,
    "free_remaining": 0,
    "estimated_cost": 0.002,
    "plans_url": "https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
    "billing_mode": "free_first"
  }
}
```

Example `403`:

```json
{
  "type": "error",
  "message": "Scraper API is not available: no proxy credentials found. Contact support or purchase a residential, datacenter or IPv6 plan."
}
```

Example `500`:

```json
{
  "type": "error",
  "message": "Scraper service unavailable. Please try again later."
}
```

Example `503`:

```json
{
  "type": "error",
  "message": "This API is temporarily unavailable while we finalize pricing. Contact support for early access."
}
```

Try it: https://app.quantumproxies.io/data-api/playground

## SEO audit

No-JS vs rendered view of a page and the diff between them.

### No-JS vs rendered SEO audit

`POST /scraper/seo-audit`

**Price:** `seo_audit` $0.0012 per call · `extract` $0.0002 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-07)_  
**Rate limit:** Per API key, by tier (see Rate limits and tiers).  
**Short alias:** `POST https://api.quantumproxies.io/v1/seo-audit` (same handler, primary host only)  
[Try it in the Playground](https://app.quantumproxies.io/data-api/playground) · [Markdown for this group](https://quantumproxies.io/docs/ai.md)

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.

#### Request body (required)

`Content-Type: application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | string | yes |  |
| `country` | string | no | Country code or place name: letters, digits, spaces, dots, hyphens, underscores; max 56 characters. `all` means no targeting. |
| `no_render` | boolean | no | Skip the rendered pass. Alias `noRender`. Default `false`. |

Example:

```json
{
  "url": "https://example.com"
}
```

#### Examples

**curl**

```bash
curl -X POST 'https://api.quantumproxies.io/v1/scraper/seo-audit' \
  -H 'Authorization: Bearer qp_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com"}'
```

**Python (requests)**

```python
import requests

r = requests.post(
    'https://api.quantumproxies.io/v1/scraper/seo-audit',
    headers={"Authorization": "Bearer qp_live_YOUR_API_KEY"},
    json={
        "url": "https://example.com"
    },
    timeout=120,
)
data = r.json()
if data["type"] != "response":
    raise SystemExit(data["message"])
print(data["payload"])
```

**Node (fetch)**

```javascript
const res = await fetch("https://api.quantumproxies.io/v1/scraper/seo-audit", {
  method: "POST",
  headers: {
    Authorization: "Bearer qp_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "url": "https://example.com"
  })
});
const data = await res.json();
if (data.type !== "response") throw new Error(data.message);
console.log(data.payload);
```

**PHP (curl)**

```php
<?php
$ch = curl_init('https://api.quantumproxies.io/v1/scraper/seo-audit');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer qp_live_YOUR_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'url' => 'https://example.com'
  ]),
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if ($data['type'] !== 'response') { throw new RuntimeException($data['message']); }
print_r($data['payload']);
```

#### Responses

- `200` — Audit finished.
- `400` — Malformed input. `message` names the parameter and the rule it broke.
- `401` — Missing, malformed, unknown, disabled or expired API key; or the account is not active.
- `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.
- `403` — No proxy pool is available to serve the call (no house plan and no residential/datacenter/IPv6 plan on the account).
- `429` — Key rate limit (hourly window), plan per-minute budget, browser-render concurrency, or pool capacity. Back off on Retry-After.
- `500` — Our side: the scraper service is unavailable or the call timed out. Never billed.
- `503` — The Data API group is switched off for non-admin keys (early-access kill switch).

Example `200` response:

```json
{
  "type": "response",
  "message": "SEO audit successful",
  "payload": {
    "url": "https://example.com",
    "finalUrl": "https://example.com/",
    "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": {}
}
```

Example `400`:

```json
{
  "type": "error",
  "message": "Invalid format. Must be one of: markdown, html, text (or data_format markdown/screenshot, format raw)"
}
```

Example `401`:

```json
{
  "type": "error",
  "message": "Missing or invalid Authorization header. Use: Authorization: Bearer qp_live_YOUR_API_KEY"
}
```

Example `402`:

```json
{
  "type": "error",
  "message": "Your free tier for this month is used up and your balance can't cover this call (estimated $0.002). Add pay-as-you-go credit or pick a plan — your API key stays the same: https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
  "payload": {
    "code": "INSUFFICIENT_FUNDS",
    "balance": 0,
    "free_remaining": 0,
    "estimated_cost": 0.002,
    "plans_url": "https://app.quantumproxies.io/plans?utm_source=api&utm_medium=402&utm_campaign=free-tier",
    "billing_mode": "free_first"
  }
}
```

Example `403`:

```json
{
  "type": "error",
  "message": "Scraper API is not available: no proxy credentials found. Contact support or purchase a residential, datacenter or IPv6 plan."
}
```

Example `429`:

```json
{
  "type": "error",
  "message": "Rate limit exceeded. Resets in 23 minutes.",
  "payload": {
    "rateLimit": 1200,
    "requestCount": 1200,
    "resetAt": "2026-10-07T15:00:00.000Z"
  }
}
```

Example `500`:

```json
{
  "type": "error",
  "message": "Scraper service unavailable. Please try again later."
}
```

Example `503`:

```json
{
  "type": "error",
  "message": "This API is temporarily unavailable while we finalize pricing. Contact support for early access."
}
```

Try it: https://app.quantumproxies.io/data-api/playground
