API Documentation

Web Scraping & Autonomous Deep Research API

Extract structured web data or execute multi-vector autonomous deep research with live crawling, multi-source evidence extraction, and synthesis.

Base URL: https://api.tafscraper.com

Authentication

All API requests require authentication using an API key. Include your key in the X-API-Key header.

X-API-Key: sk_your_api_key_here

Get your API key from the dashboard.

Credit System

  • Free Credits — Can only be used for basic scraping (no context).
  • Purchased Credits — Required for contextual/AI scraping.
  • Each page scraped consumes 1 credit.
POST/api/v1/scrape

Description

Starts a web scraping job for the specified URL. Returns cached results immediately if available, otherwise starts an asynchronous job.

Request Body

{
  "url": "https://example.com",
  "context": "Extract all email addresses",
  "config": {
    "max_pages": 10,
    "max_depth": 2,
    "delay_ms": 1000,
    "follow_external_links": false,
    "scrape_css_branding": false
  }
}

Parameters

url(required)

The URL to scrape. Must be a valid HTTP/HTTPS URL.

context(optional)(Requires Purchased Credits)

AI extraction prompt. Specify what data you want to extract.

config.max_pages(optional, default: 10)

Maximum number of pages to scrape.

config.max_depth(optional, default: 2)

Maximum depth to follow links.

config.delay_ms(optional, default: 1000)

Delay between requests in milliseconds.

config.follow_external_links(optional, default: false)

Whether to follow links to external domains.

config.structured(optional, default: false)

Opt in to a structured site object on every page (schema version "2"): brand, navigation, CTAs, sections, FAQ, latest posts, images with context, contacts and SEO. Collapsed content such as closed <details> is included, and Cloudflare-protected emails are decoded. Existing fields are unchanged and the same credit cost applies. See Structured site output.

config.scrape_css_branding(optional, default: false)

Whether to extract branding. Each page then includes logo (URL, or an SVG data URI for inline SVG logos), favicon, and colors (primary, secondary, tertiary as #rrggbb). Linked stylesheets are fetched to detect colors.

Response (Job Started)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "started",
  "message": "Scraping job started for URL: https://example.com",
  "cached": false,
  "data": null
}

Response (Cached)

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "message": "Scraping completed",
  "cached": true,
  "data": [
    {
      "url": "https://example.com",
      "title": "Example Domain",
      "text_content": ["Welcome to example.com", "..."],
      "links": ["https://example.com/about"],
      "images": ["https://example.com/logo.png"]
    }
  ]
}

Structured site output

Send config.structured: true to POST /api/v1/scrape. Each page in data (and in the job results) then carries a site object. Jobs started without the flag return exactly the response shown above.

curl -X POST https://api.tafscraper.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -H "X-API-Key: sk_your-api-key" \
  -d '{"url": "https://tinnitaid.com", "config": {"max_pages": 1, "structured": true}}'

Response (trimmed)

{
  "url": "https://tinnitaid.com/",
  "title": "Tinnitaid - Calm the noise—anytime, anywhere.",
  "text_content": ["..."],
  "site": {
    "schema_version": "2",
    "brand": { "name": "Tinnitaid", "source": "og:site_name" },
    "primary_nav": [
      { "label": "Articles", "href": "https://tinnitaid.com/blog/", "source": "header_nav", "selector": "..." },
      { "label": "Privacy Policy", "href": "https://tinnitaid.com/privacy-policy/", "source": "header_nav", "selector": "..." }
    ],
    "footer_nav": [],
    "primary_cta": {
      "label": "Open App", "href": "https://app.tinnitaid.com", "count": 3,
      "regions": ["hero", "section"], "source": "button_like_link", "selector": "..."
    },
    "sections": [
      { "index": 0, "region": "hero", "heading": "Tinnitaid",
        "subheading": "Calm the noise—anytime, anywhere.",
        "text": "...", "html": "...", "images": ["img_2"], "ctas": ["Open App", "How it works"] }
    ],
    "faq": [
      { "question": "What is Tinnitaid?", "answer_text": "...", "answer_html": "...", "source": "details", "selector": "..." }
    ],
    "latest_posts": [
      { "title": "Can stress worsen tinnitus?", "url": "https://tinnitaid.com/can-stress-worsen-tinnitus/", "excerpt": "..." }
    ],
    "images": [
      { "id": "img_3", "url": "https://tinnitaid.com/wp-content/uploads/2024/06/kifissia_...png",
        "alt": "Kifissia Award", "kind": "award_badge", "section_index": 3,
        "nearest_heading": "Awards / Investors / Partners", "region": "section", "status": "ok", "error": null }
    ],
    "contacts": {
      "emails": [{ "value": "[email protected]", "source": "cfemail", "selector": "..." }],
      "phones": []
    },
    "seo": { "title": "...", "description": "...", "canonical": "https://tinnitaid.com/", "og_image": "...", "lang": "en-US" },
    "warnings": []
  }
}

Every extracted item carries source (how it was found) and selector (a CSS path).

contacts.phones only contains tel: links and keyword-adjacent numbers that validate for the site's country; citation numbers such as DOIs and PMIDs are never reported as phones.

images that cannot be resolved stay in the list with status: "failed" and an error, plus a matching entry in warnings. A js_rendered_suspected warning means the page looks client-side rendered and only its static HTML was read.

GET/api/v1/jobs/:job_id

Description

Check the status of a scraping job. Poll this endpoint until status is completed or failed.

Path Parameters

job_id(required)

The UUID returned by the scrape endpoint.

Response

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "message": "Job completed successfully. Scraped 15 pages",
  "progress": {
    "pages_scraped": 15,
    "total_links_found": 120,
    "current_url": null
  },
  "results": null,
  "error": null
}

Status Values

  • pending — Job is queued
  • running — Job is in progress
  • completed — Job finished successfully
  • failed — Job encountered an error

Code Examples

cURL

curl -X POST https://api.tafscraper.com/api/v1/scrape \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "config": {
      "max_depth": 2,
      "max_pages": 10
    }
  }'

JavaScript

const response = await fetch('https://api.tafscraper.com/api/v1/scrape', {
  method: 'POST',
  headers: {
    'X-API-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    config: {
      max_depth: 2,
      max_pages: 10
    }
  })
});

const data = await response.json();

if (data.cached) {
  console.log('Scraped data:', data.data);
} else {
  // Poll for job completion
  const jobId = data.job_id;
  let status = 'pending';
  
  while (status !== 'completed' && status !== 'failed') {
    await new Promise(r => setTimeout(r, 2000));
    const statusRes = await fetch(`https://api.tafscraper.com/api/v1/jobs/${jobId}`, {
      headers: { 'X-API-Key': 'YOUR_API_KEY' }
    });
    const statusData = await statusRes.json();
    status = statusData.status;
    console.log('Job status:', status);
  }
}

Python

import requests
import time

headers = {
    'X-API-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
}

# Start scraping
response = requests.post('https://api.tafscraper.com/api/v1/scrape', 
    headers=headers,
    json={
        'url': 'https://example.com',
        'config': {
            'max_depth': 2,
            'max_pages': 10
        }
    }
)

data = response.json()

if data['cached']:
    print('Scraped data:', data['data'])
else:
    job_id = data['job_id']
    
    # Poll for completion
    while True:
        status_res = requests.get(
            f'https://api.tafscraper.com/api/v1/jobs/{job_id}',
            headers=headers
        )
        status_data = status_res.json()
        
        if status_data['status'] in ['completed', 'failed']:
            print('Final status:', status_data['status'])
            break
        
        time.sleep(2)

Autonomous Deep Research

Autonomous multi-vector research engine. Inspired by Valyu.ai, it decomposes inquiries into targeted search vectors, scans the live web, extracts real-world evidence, and synthesizes cited research reports.

POST/api/v1/deepresearch

Request Body

{
  "query": "Impact of synthetic biology on agriculture 2026",
  "mode": "fast",
  "research_strategy": "Focus on nitrogen fixation, soil micro-biomes, and commercial cost curves",
  "report_format": "Executive brief with comparative domain tables",
  "seed_urls": [
    "https://example.com/agtech-whitepaper.pdf"
  ]
}
query(required)

The research topic or question to investigate.

mode(optional: "fast" | "standard" | "heavy", default: "fast")

fast (1 credit): 2 search vectors, instant synthesis (~10-15s).
standard (5 credits): 4 search vectors, cross-domain verification (~25-35s).
heavy (25 credits): 6+ search vectors, multi-page deep analysis (~45-60s).

research_strategy(optional)

Specific research angle, domain focus, or hypotheses to test.

seed_urls(optional)

Prioritized URLs to crawl and incorporate into the evidence pool.

Response (Task Initiated)

{
  "deepresearch_id": "b5e2a251-b53c-4006-98f8-60851f648da5",
  "status": "running",
  "mode": "fast",
  "credits_used": 1,
  "message": "Deep research task started in fast mode (1 credits deducted)",
  "created_at": "2026-10-15T11:38:10.135Z"
}
GET/api/v1/deepresearch/:task_id

Response (Completed Task with Report & Citations)

{
  "id": "b5e2a251-b53c-4006-98f8-60851f648da5",
  "query": "Impact of synthetic biology on agriculture 2026",
  "mode": "fast",
  "status": "completed",
  "credits_used": 1,
  "output": "# Deep Research Report: Impact of synthetic biology on agriculture 2026\n\n## Executive Summary...",
  "sources": [
    {
      "title": "Synthetic Biology in Modern Farming 2026",
      "url": "https://example.org/synbio-agri",
      "snippet": "Engineered microbes reduced synthetic fertilizer dependency by 38%..."
    }
  ],
  "steps_log": [
    { "step": 1, "title": "Formulating Research Strategy", "status": "completed", "details": "Generated 2 targeted search vectors" },
    { "step": 2, "title": "Autonomous Web & Academic Discovery", "status": "completed", "details": "Identified candidate sources" },
    { "step": 3, "title": "Deep Content Extraction & Fact Parsing", "status": "completed", "details": "Extracted evidentiary content" },
    { "step": 4, "title": "Synthesizing Deep Research Report", "status": "completed", "details": "Report authored with citations" }
  ],
  "created_at": "2026-10-15T11:38:10.128Z",
  "completed_at": "2026-10-15T11:38:25.237Z"
}

Error Responses

401 Unauthorized

{
  "error": "Invalid API key",
  "status": 401
}

402 Payment Required

{
  "error": "Insufficient credits",
  "status": 402
}

404 Not Found

{
  "error": "Job 550e8400-e29b-41d4-a716-446655440000 not found",
  "status": 404
}

429 Too Many Requests

{
  "error": "Rate limit exceeded",
  "status": 429
}

Rate Limits

EndpointLimit
/api/v1/scrape30 requests / minute
/api/v1/jobs/:job_id30 requests / minute
Ask TafScraper's AI