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
Deep Research
POST /api/v1/deepresearch
Start Scraping
POST /api/v1/scrape
Check Status
GET /api/v1/jobs/:id
Authentication
X-API-Key header
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_hereGet 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.
/api/v1/scrapeDescription
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.
/api/v1/jobs/:job_idDescription
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 queuedrunning— Job is in progresscompleted— Job finished successfullyfailed— 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.
/api/v1/deepresearchRequest 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"
}/api/v1/deepresearch/:task_idResponse (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
| Endpoint | Limit |
|---|---|
/api/v1/scrape | 30 requests / minute |
/api/v1/jobs/:job_id | 30 requests / minute |