Skip to content

API Documentation

From a URL to usable data. Start with one request, then add structured extraction, browser rendering or background jobs.

On this page

Base URL

https://api.finedata.ai

Quick Start

Create an account, copy your API key from the dashboard, and replace fd_your_api_key below. This request reads a public page and returns markdown.

curl

curl -X POST https://api.finedata.ai/api/v1/scrape \
  -H "Content-Type: application/json" \
  -H "x-api-key: fd_your_api_key" \
  -d '{"url": "https://example.com", "formats": ["markdown"]}'
Python · requests

Install with pip install requests. Run on your server, not in a public client.

import requests

resp = requests.post(
    "https://api.finedata.ai/api/v1/scrape",
    headers={"x-api-key": "fd_your_api_key"},
    json={"url": "https://example.com", "formats": ["markdown"]},
    timeout=130,
)
resp.raise_for_status()
data = resp.json()
if data["success"] is False:
    raise RuntimeError(data)
print(data["data"]["markdown"])
JavaScript · Node.js 18+

Run as an ES module on your server. Never expose your API key in browser code.

const resp = await fetch("https://api.finedata.ai/api/v1/scrape", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": "fd_your_api_key" },
  body: JSON.stringify({ url: "https://example.com", formats: ["markdown"] })
});
if (resp.ok === false) throw new Error(await resp.text());
const data = await resp.json();
if (data.success === false) throw new Error(JSON.stringify(data));
console.log(data.data.markdown);

Authentication

All requests require one of:

API Key (recommended)

curl -X POST https://api.finedata.ai/api/v1/scrape \
  -H "x-api-key: fd_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","formats":["markdown"]}'

JWT Bearer Token

curl -X POST https://api.finedata.ai/api/v1/scrape \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","formats":["markdown"]}'

Token Pricing

Tokens are API usage credits, not LLM input tokens. A default request uses 3: 1 base + 2 for TLS fingerprinting. Failed scrapes are not billed. Add one rendering mode and any routing, extraction or action costs you need.

1
Base request
+2
Antibot (TLS)
+5
JS Render
+7
Stealth Antibot
+15
Stealth New
+25
Stealth Headful
+20
Stealth Premium
+30
Premium Headful
+2
ISP
+5
AI extraction
+2
Per browser action
+3
Residential
+4
Mobile
+10
Captcha
+1
Per retry
+1
BYOP (own proxy)
+0
Geo-targeting
Examples: HTTP with use_antibot: false = 1 · With antibot = 3 · JS render = 8 · Stealth + residential = 13 · Stealth Headful = 28
Examples assume no retries or extraction. A domain-specific strategy may change the engine or routing: use the response's tokens_used as the actual charge. A Google SERP request is a flat 10 tokens, reported as tokens_charged; a blocked or empty Google response is not billed and gl, hl and start do not change the price.

Scrape Endpoint

POST /api/v1/scrape

Send a JSON body with a target URL. Add only the options your page needs.

{
  "url": "https://example.com",
  "formats": ["markdown"],
  "only_main_content": true
}
Request options
url
Required target URL. The API call itself is always POST; method selects the request sent to the target.
method · headers · body
GET by default. For a write request, pass its method, target headers and a string body.
timeout
120 seconds by default; allowed range 5–300. Set your HTTP client timeout slightly higher.
max_retries · auto_retry
max_retries: 5 by default (1–10). auto_retry: true; actual retries add 1 token each.
Rendering options
use_antibot · tls_profile
TLS fingerprinting is on by default, with chrome136 (+2 tokens).
use_js_render
Render JavaScript (+5). Use for pages whose content loads in the browser.
stealth_antibot · stealth_antibot_headful
Stronger browser emulation (+7) or a full headful browser (+25).
stealth_premium · stealth_premium_headful
Premium fingerprint emulation (+20), or its headful mode (+30).
stealth_new
Experimental rendering mode (+15). Choose one rendering mode rather than stacking flags.
js_wait_for · js_scroll · js_actions
Wait for a load event or selector, scroll, or run up to 10 browser actions (+2 each).
Routing and output options
use_isp · use_residential · use_mobile
Choose one proxy type: ISP (+2), residential (+3), or mobile (+4). Datacenter is the default.
proxy_country · proxy_profile_id
Choose a country or a saved BYOP profile, not both. See Proxy & Geo-Targeting below.
session_id · session_ttl · proxy_sticky
Reuse a session (TTL: 60–86,400 seconds; default 1,800) and request a sticky exit IP.
formats · only_main_content · raw_output
Select output fields, remove page chrome, or return one format without the JSON wrapper.
extract_rules · extract_prompt · extract_schema
Extract with CSS/XPath selectors or AI. See working examples below.

For every field and constraint, use the interactive reference or OpenAPI schema.

Response

Illustrative response, shortened for readability. Only requested output fields are populated.

{
  "success": true,
  "status_code": 200,
  "body": "<html>...</html>",
  "data": {
    "markdown": "# Example Domain\n\nThis domain is for use..."
  },
  "meta": {"url": "https://example.com", "elapsed_ms": 1250},
  "tokens_used": 3
}

Check the API HTTP status first, then success. The JSON field status_code is the target page's status, not the API's. Read content from data.markdown and actual usage from tokens_used.

Google SERP

POST /api/v1/serp

Run a Google search server-side and get the results as JSON. It uses the same API-key authentication as /api/v1/scrape. The API builds the Google URL from your query, so you never send a target URL. Use it to monitor the ranking and visibility of your own domains and brand queries. Follow the Acceptable Use Policy: the permitted case is SEO and SERP tracking for your own domains.

curl -X POST https://api.finedata.ai/api/v1/serp \
  -H "Content-Type: application/json" \
  -H "x-api-key: fd_your_api_key" \
  -d '{"q": "rank tracking tool", "gl": "us", "hl": "en", "start": 0}'
Field Type Description
qstringRequired search query, 1–2048 characters.
glstringGoogle country as an ISO 3166-1 alpha-2 code, e.g. us. Defaults to us.
hlstringGoogle interface language, e.g. en or en-GB. Defaults to en.
startintegerResult offset for paging: 0–90 in steps of 10. 10 results per page; defaults to 0.
devicestringOnly desktop is supported.
include_htmlbooleanAlso return the raw Google HTML in raw_html. Defaults to false.

Response

Illustrative response, shortened for readability. Blocks such as ads, answer_box, knowledge_graph, top_stories, local_results, people_also_ask, related_searches, shopping_results and video_results appear only when the page carries them.

{
  "search_metadata": {
    "id": "3f6c1e9a-…",
    "status": "ok",
    "created_at": "2026-10-13T12:00:00+00:00",
    "processing_time_ms": 1840,
    "google_url": "<google search url built from q, gl, hl, start>"
  },
  "search_information": {
    "query_displayed": "rank tracking tool",
    "total_results": 412000000
  },
  "organic_results": [
    {
      "position": 1,
      "title": "Rank Tracking Tool — Example",
      "link": "https://example.com/rank-tracker",
      "displayed_link": "example.com › rank-tracker",
      "snippet": "Track keyword positions for your own domains…",
      "sitelinks": [
        {"title": "Pricing", "link": "https://example.com/pricing"}
      ]
    }
  ],
  "tokens_charged": 10
}

Each request costs a flat 10 tokens, reported as tokens_charged; gl, hl and start do not change the price. Links resolve away from Google's redirect wrapper, so organic_results[].link is the destination URL. A blocked or unparseable Google page costs nothing.

Code Error Action
402trial_exhausted · token_limit_exceededUpgrade the plan or add tokens
502serp_blocked · serp_emptyRetry later; nothing was charged
503Worker pool busyRetry after a short delay

Over MCP the same search is the google_search tool with arguments q, gl, hl and start; it needs the scrape:write scope. See MCP Integration.

Output Formats

Use the formats array to control what appears in data.

Format Returns Best for
markdownClean MarkdownLLM input, content extraction
textPlain textSearch indexing, NLP
rawHtmlHTML in data.raw_htmlHTML parsing
linksArray of URLsCrawling, link analysis
screenshotBase64 PNG; requires browser renderingVisual verification
csvCSV string in data.csvAI extraction to a table (sync only)
xlsxBase64 workbook in data.xlsxAI extraction to a spreadsheet (sync only)

Content without the wrapper

REST returns raw HTML in body if you omit formats. Request a format explicitly. For content-only output, add raw_output: true with exactly one format.

{
  "url": "https://example.com",
  "formats": ["markdown"],
  "raw_output": true
}

The response is markdown, not JSON. Metadata moves to X-Tokens-Used, X-Request-Id and X-Status-Code headers. CSV/XLSX require extract_prompt or extract_schema; use the synchronous endpoint for these exports.

AI Extraction

Extract with CSS/XPath selectors (no extra extraction fee) or AI (+5 tokens). AI-only results are in data.extract; when combined with selector results, AI data is nested under data.extract.ai_extract. These product URLs and selectors are illustrative.

CSS Selectors (no extra fee)

{
  "url": "https://example.com/product",
  "extract_rules": {
    "title": "h1",
    "price": ".product-price",
    "images": {"selector": "img.product-image", "type": "list", "output": "@src"}
  }
}

AI with Natural Language (+5 tokens)

{
  "url": "https://example.com/product",
  "formats": ["markdown"],
  "extract_prompt": "Extract product name, price, rating, and availability"
}

AI with JSON Schema (+5 tokens)

{
  "url": "https://example.com/product",
  "extract_schema": {
    "type": "object",
    "properties": {
      "name": {"type": "string"},
      "price": {"type": "number"},
      "in_stock": {"type": "boolean"}
    }
  }
}

For AI extraction, ai_content_mode: "full" is the default and includes sidebars and structured data. Use "main" for article-focused extraction. Check extracted fields against your application's requirements before relying on them.

Render, wait, then extract

For JavaScript pages, wait for the content you need rather than adding an arbitrary delay. This illustrative sequence expands a product description before extraction; replace the URL and selectors with your page's.

{
  "url": "https://example.com/product",
  "use_js_render": true,
  "js_wait_for": "selector:.product",
  "js_actions": [
    {"action": "click", "selector": ".expand-description"},
    {"action": "wait_for", "selector": ".description-expanded"}
  ],
  "extract_prompt": "Extract the product name and full description"
}

Up to 10 actions: click, wait, wait_for, scroll, type, hover, screenshot, evaluate. Browser interactions can change the target site: use only actions you are authorized to perform.

Async & Batch Scraping

Background processing for large-scale scraping or slow pages.

POST /api/v1/async/scrape

Submit a job, get job_id immediately. Use webhook or poll for results.

{
  "url": "https://example.com",
  "formats": ["markdown"]
}
GET /api/v1/async/jobs/{job_id}

Poll status: pending, processing, completed, failed, cancelled

GET /api/v1/async/jobs

List your jobs with pagination

DELETE /api/v1/async/jobs/{job_id}

Cancel a pending job. A processing job cannot be cancelled and returns HTTP 400.

POST /api/v1/async/batch

Submit up to 100 URLs in one request

Submit a batch and collect results

POST this body to /api/v1/async/batch. REST uses requests, an array of request objects; the MCP batch_scrape tool uses urls instead.

{
  "requests": [
    {"url": "https://example.com", "formats": ["markdown"]},
    {"url": "https://example.org", "formats": ["markdown"]}
  ]
}

Save the returned batch_id. Poll with a delay between requests, adding include_results=true to retrieve individual results.

curl "https://api.finedata.ai/api/v1/async/batch/YOUR_BATCH_ID?include_results=true" \
  -H "x-api-key: fd_your_api_key"

Stop polling at completed, partial or failed. For a single job, terminal states are completed, failed and cancelled; completed output is in result.data. An optional callback_url notifies your public endpoint when work finishes.

Captcha Solving

Set solve_captcha: true to auto-detect and solve (+10 tokens).

reCAPTCHA v2/v3hCaptchaCloudflare TurnstileYandex SmartCaptchaFunCaptchaGeeTest

TLS Profiles

Set tls_profile to mimic a browser fingerprint.

Chrome

chrome136 (default)chrome131chrome124chrome123chrome120

Firefox · Safari · Mobile

firefox133safari184safari18_0safari17_0chrome131_androidsafari18_0_ios

VIP (Premium auto-rotate)

vipvip:iosvip:androidvip:windowsvip:mobile

Proxy & Geo-Targeting

Geo-Targeting

Set proxy_country to an ISO-2 country code to request a proxy exit IP from that country. Works with datacenter, residential, ISP, and mobile proxies at no extra cost. Returns 422 if the country isn't currently supported for the resolved proxy type.

{
  "url": "https://example.com",
  "use_residential": true,
  "proxy_country": "DE"
}

Bring Your Own Proxy (BYOP)

Save your own proxy list as a profile in the dashboard, then reference it with proxy_profile_id. Proxies are encrypted at rest. BYOP charges a flat +1 token instead of the vendor proxy surcharge, and is mutually exclusive with use_residential / use_isp / use_mobile / proxy_country.

{
  "url": "https://example.com",
  "proxy_profile_id": 42,
  "proxy_sticky": true
}

Available on PAYG, Team S/M/L and Scaling, or with an account override. Combine with proxy_sticky: true to keep the same exit IP for an entire browser session — useful for anti-bot flows where warmup and API calls must share one IP.

Error Codes

These are API HTTP errors. Inspect the response's detail for the cause. A target-page failure can instead arrive in a scrape result with success: false; inspect its status_code and metadata before retrying.

Code Description Action
401 Invalid or missing API key / JWT token Check your API key
402 Payment required Upgrade plan or pay invoices
403 Account or feature access denied Read the error; check plan, scopes or account status
422 Validation error Check request parameters
429 Rate limit exceeded Reduce request frequency; respect Retry-After when present
500 Internal server error Retry or contact support
503 Service unavailable Retry after a moment

MCP Integration

Connect FineData to Claude Desktop, Cursor IDE, and other AI agents via MCP (v0.3.1). Full setup, tool reference, OAuth sign-in and cost guidance: the MCP server page. Tools: scrape_url (GET), send_http_request (POST/PUT/PATCH/DELETE), scrape_async, get_job_status, cancel_job, list_jobs, batch_scrape, get_batch_status, get_usage. Start with a default request. Add rendering or routing only when the page needs it; use the tool's error hints rather than enabling the most expensive mode by default.

{
  "mcpServers": {
    "finedata": {
      "command": "npx",
      "args": ["-y", "@finedata/mcp-server"],
      "env": { "FINEDATA_API_KEY": "fd_your_api_key" }
    }
  }
}

Remote (Streamable HTTP):

{
  "mcpServers": {
    "finedata": {
      "url": "https://mcp.finedata.ai/mcp",
      "headers": { "Authorization": "Bearer fd_your_api_key" }
    }
  }
}

Rate Limits

Plan Requests/second Tokens/month Overage
Free Trial 5 10,000 Blocked
Free 2 1,000 Blocked
PAYG 10 Unlimited $0.55/1K
Personal 20 100,000 $0.55/1K
Team S 50 1,000,000 $0.55/1K
Team M 100 3,000,000 $0.55/1K
Team L 200 5,000,000 $0.55/1K
Scaling 400 10,000,000 $0.55/1K

Free plans block when exhausted. Paid plans allow overage at $0.55/1K tokens.