Setup
composer require guzzlehttp/guzzle # or use the built-in curl extension
Get a key at app.quanticdata.io/register: no card, keys start with qd_live_, and every account has $2 of credit a month. Base URL https://api.quanticdata.io/v1, header Authorization: Bearer qd_live_…. The full parameter reference is the API reference and the OpenAPI file; this page is the PHP path through it.
The envelope
Every data call answers with the same shape: ok, payload with the result, and payload.usage with the cost. Errors come back as ok: false with error.code and error.message, and are not billed.
Scrape a page
POST /v1/scrape · $0.0002 per page
<?php
$ch = curl_init("https://api.quanticdata.io/v1/scrape");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://example.com",
"format" => "markdown"
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
payload.content is the Markdown; payload.usage is what the call cost. Add render: true for JavaScript pages ($0.001) or engine: "tls" to refuse escalation.
Search results
POST /v1/serp · $0.0005 per search
<?php
$ch = curl_init("https://api.quanticdata.io/v1/serp");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"query" => "best coffee grinder",
"engine" => "google",
"country" => "us"
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
payload.organic is the list of results; ai_overview, people_also_ask and related_searches ride along when Google returns them.
Map a site
POST /v1/map · $0.0005 per site
<?php
$ch = curl_init("https://api.quanticdata.io/v1/map");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://example.com",
"limit" => 100
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
Every URL the site exposes through sitemaps and homepage links, with a per-section summary. Use search to filter or group_by: "path" for the tree.
Crawl a site
POST /v1/crawl · $0.0003 per page
<?php
$ch = curl_init("https://api.quanticdata.io/v1/crawl");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://example.com",
"limit" => 50,
"depth" => 3,
"format" => "markdown"
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
Async. The response carries a jobId; poll GET /v1/crawl/{jobId} until status is done. Pages not fetched are refunded.
Batch of URLs
POST /v1/batch · $0.0002 per URL
<?php
$ch = curl_init("https://api.quanticdata.io/v1/batch");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"urls" => [
"https://example.com/a",
"https://example.com/b"
],
"format" => "markdown",
"concurrency" => 5
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
Up to 1,000 URLs per job, async; poll GET /v1/batch/{jobId} or pass a webhook URL.
SEO audit
POST /v1/seo-audit · $0.0012 per URL
<?php
$ch = curl_init("https://api.quanticdata.io/v1/seo-audit");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://example.com"
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
Fetches the URL as a plain HTTP client and as a rendered browser, and returns both views plus the diff: title, description, canonical, h1, word count, JS-only content.
Run a collector
POST /v1/scraper/collectors/google_maps_places/run · from $0.0005 per result
<?php
$ch = curl_init("https://api.quanticdata.io/v1/scraper/collectors/google_maps_places/run");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"query" => "pizza restaurants",
"location" => "Brooklyn, NY",
"country" => "us",
"max_results" => 20
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
Collectors take a semantic input, never a URL. A 200 is a finished run; a 202 is async, poll GET /v1/scraper/collectors/runs/{runId}. Billed per delivered row.
Generate proxy strings
POST /v1/public/proxies/generate · no charge; bandwidth is billed by the plan
<?php
$ch = curl_init("https://api.quanticdata.io/v1/public/proxies/generate");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer qd_live_YOUR_KEY",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"orderId" => "your_order_id",
"protocol" => "http",
"format" => "user:pass@host:port",
"quantity" => 10,
"country" => "us",
"rotation" => "rotating"
]),
]);
$raw = curl_exec($ch);
$data = json_decode($raw, true);
print_r($data["payload"]);
GET /v1/public/proxies lists your plans and their orderId. The generator returns ready-to-use endpoint strings for a country, state or city.
Errors you will see
- 401 — missing or wrong key. Keys are case-sensitive and start with
qd_live_. - 402 — credit exhausted on pay-as-you-go; add a payment method or wait for the monthly $2.
- 422 — the body did not validate: the message names the field.
- 429 — account rate limit; honour
Retry-After. - ok: false with a 200 — the target could not be fetched (blocked, timed out, gone). Not billed; the error code says which.
Prices for every unit are on the pricing page. Agents can skip the HTTP layer entirely with the MCP server, which exposes the same calls as tools.
Guides for PHP developers
Longer walkthroughs from the blog that use the same key and gateway:
Questions about the API in PHP
Do I need an SDK to use the API from PHP?
How do I know what a call cost?
payload.usage with cost_usd, the part covered by free credit and the part charged. Failed calls return an error envelope and cost nothing.What happens on rate limits?
Can I get the response as JSON instead of Markdown?
format accepts markdown, html, text or raw, and extract takes CSS selectors or a JSON schema with an AI prompt to return structured fields under payload.data.Run the PHP examples now
A free key takes a minute, and the $2 of monthly credit covers about 10,000 scraped pages.
Get my free API keyFree key, $2 of usage credit every month, no credit card.