ScavioScavio
Pricing
Tools
Sign InsGet Startedg
Quick StartAPI & SDKsEcosystem

Extract

Crawl a Website

Start a crawl from one URL and get every same-site page back as Markdown, plain text or HTML, exactly like Extract. Pages are discovered breadth-first from the start page and the site's sitemap, within your depth, page and path limits, and pages disallowed by robots.txt are skipped. Returns 202 with a job id at once; poll the status URL or take a signed webhook when it finishes. Billed per successful page at Extract's price (normal 1, advanced 1, ultra 2); failed and skipped pages are free.

POST/api/v1/extract/crawl

Authorizations

Authorizationstringheaderrequired

Bearer authentication header of the form Bearer <token>, where <token> is your Scavio API key (e.g. Bearer sk_live_your_key).

Body

application/json
urlstringrequired

Where the crawl starts, 1-2048 characters. Only pages on the same site are crawled (www and the bare domain count as one site). Pages under the start URL's path are crawled first.

Example: https://hono.dev/docs

max_pagesintegerdefault:100

Maximum pages to fetch, 1-10,000. Must be within your plan's limit: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000. Above it is a 400 that names the cap.

max_depthintegerdefault:3

How many links away from the start page to follow, 0-10. 0 fetches only the start page.

include_pathsstring[]

Path globs to crawl, max 50. * matches within one path segment, ** across segments, and a pattern with no wildcard matches that path and everything under it (["/docs"] covers /docs and /docs/anything).

Example: ["/docs"]

exclude_pathsstring[]

Path globs to skip, same syntax. Excludes win over includes.

Example: ["/blog/tag/*"]

allow_subdomainsbooleandefault:false

Also crawl subdomains of the site, such as docs.example.com when starting on example.com.

ignore_query_parametersbooleandefault:true

Treat URLs that differ only by query string as one page, so ?ref= and ?sort= variants are not fetched twice.

sitemapenum<string>default:include

Whether the site's sitemap seeds the crawl.

  • include — Start from the start page and the sitemap, then follow links. The default.
  • skip — Follow links from the start page only.
  • only — Fetch the sitemap's pages without following links.
formatenum<string>default:markdown

Return format for every page, as on Extract.

  • markdown — Clean Markdown with links kept, ready for an LLM, a vector store or RAG. The default.
  • text — The same content flattened to plain text.
  • html — The raw page as served.
modeenum<string>default:normal

Fetch tier for every page, and the price per page.

  • normal — The standard fetch. 1 credit per successful page. Right for docs, blogs and most sites.
  • advanced — Renders JavaScript, for pages whose content is built in the browser. 1 credit per successful page.
  • ultra — For the hardest pages. 2 credits per successful page.
webhook_urlstring

Optional public https URL that receives one signed POST when the crawl completes, fails or is cancelled. The signing secret comes back once, in the 202, as webhook_secret. See Webhooks below.

Idempotency-Keystringheader

Optional, max 255 characters. Repeating the POST with the same key within 24 hours returns the original job instead of starting a second one, so a retried request never doubles a crawl.

Notes

How a crawl runs. The crawl starts at url, reads the site's robots.txt and (unless sitemap is skip) its sitemap, then fetches same-site pages breadth-first, following the links on each page up to max_depth. Pages under the start URL's path go first, so a crawl started at /docs spends its pages on the docs before the rest of the site. It never leaves the site, never fetches the same URL twice and stops at max_pages (stopped_reason: "max_pages").

Robots.txt is always obeyed. Disallowed pages are not fetched; they appear in the results as skipped with skip_reason: "robots" and cost nothing. A Crawl-delay in robots.txt is honoured up to 5 seconds. There is no override.

Pricing: successful pages only. Each page that comes back is charged once, at Extract's price for the tier: normal 1 credit, advanced 1, ultra 2 (credits_per_page in the 202). Failed pages, 404s, robots-skipped pages and the robots.txt and sitemap reads cost nothing, and starting, polling and cancelling are free. Credits are taken page by page as the crawl runs; you need one page's cost to start, and if your balance runs out the crawl stops cleanly with stopped_reason: "insufficient_credits", keeping every page it already fetched.

Plan limits. Pages per crawl, crawl and batch jobs running at once, and URLs per batch:

PlanPages per crawlActive jobsURLs per batchMap links
Free10110500
PAYG1001501,000
Project50021005,000
Bootstrap2,00035005,000
Startup5,00051,0005,000
Growth10,000101,0005,000

Starting a job while your plan's active jobs are still running returns a 429 with running_jobs and a Retry-After header. Per-request concurrency limits apply to the POST itself, not to the pages a crawl fetches.

Retention and size. Results are kept for 3 days after the job finishes (expires_at), then deleted; copy what you need. Each page stores up to 2 MB of content (truncated: true beyond that) and each job up to 250 MB (stopped_reason: "storage_limit"). A job runs for at most 6 hours (stopped_reason: "time_limit").

Results. Read them from Crawl Status, paged by cursor. Stop a crawl early with Cancel Crawl. To list a site's URLs without fetching them, use Map; to extract a list of URLs you already have, use Batch Extract.

Webhooks. Set webhook_url to a public https URL and Scavio POSTs one signed JSON event when the crawl ends: event is completed, failed or cancelled, job is the same summary the status endpoint returns, and sent_at is the send time. Results are not in the body; fetch them from the status URL. Headers: Scavio-Signature, Scavio-Event and Scavio-Job-Id. A delivery that does not get a 2xx within 10 seconds is retried twice, 30 seconds and 5 minutes after the first attempt. Redirects are not followed, and the URL must use a public host name (no IP addresses or private hosts).

Verify every delivery. The 202 response returns webhook_secret (whsec_...) once; store it. Scavio-Signature is t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of <t>.<raw request body> keyed with that secret. Recompute it over the raw bytes, compare in constant time, and reject timestamps more than 5 minutes old:

import hashlib, hmac, time

def verify_scavio_signature(secret: str, header: str, raw_body: bytes, tolerance: int = 300) -> bool:
    """header is the Scavio-Signature value: t=<unix>,v1=<hex>."""
    parts = dict(p.strip().split("=", 1) for p in header.split(",") if "=" in p)
    t, v1 = parts.get("t", ""), parts.get("v1", "")
    if not t.isdigit() or not v1 or abs(time.time() - int(t)) > tolerance:
        return False
    signed = t.encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

# Flask example
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_from_the_202_response"

@app.post("/scavio/webhook")
def scavio_webhook():
    if not verify_scavio_signature(WEBHOOK_SECRET, request.headers.get("Scavio-Signature", ""), request.get_data()):
        abort(400)
    event = request.get_json()
    print(event["event"], event["job"]["id"], event["job"]["pages"]["succeeded"])
    return "", 204

A delivery body looks like this:

{
  "event": "completed",
  "job": {
    "id": "crawl_01a12d2e-f813-73c2-8c07-4c1f0ae402df",
    "type": "crawl",
    "status": "completed",
    "stopped_reason": null,
    "error": null,
    "url": "https://example.com/",
    "format": "markdown",
    "mode": "normal",
    "pages": { "discovered": 1, "queued": 0, "succeeded": 1, "failed": 0, "skipped": 0 },
    "credits_used": 1,
    "created_at": "2026-10-11T22:56:55.312Z",
    "started_at": "2026-10-11T22:57:00.424Z",
    "completed_at": "2026-10-11T22:57:02.665Z",
    "expires_at": "2026-10-14T22:57:02.665Z",
    "webhook": { "status": "pending", "attempts": 1 },
    "status_url": "https://api.scavio.dev/api/v1/extract/crawl/crawl_01a12d2e-f813-73c2-8c07-4c1f0ae402df"
  },
  "sent_at": "2026-10-11T22:57:02.701Z"
}

Request

import time
from scavio import ScavioClient

client = ScavioClient(api_key="sk_live_your_key")

# Start the crawl: 202 with a job id, 0 credits so far
job = client.extract.crawl("https://hono.dev/docs", max_pages=50, include_paths=["/docs"])
job_id = job["data"]["id"]

# Poll until it finishes (or pass wait=True to crawl() to do this for you)
while True:
    status = client.extract.crawl_status(job_id, include_content=False)
    if status["data"]["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(5)

# Page through the results, 25 per response by default
cursor = None
while True:
    page = client.extract.crawl_status(job_id, cursor=cursor)
    for r in page["data"]["results"]:
        print(r["status"], r["url"], r["content_length"])
    cursor = page["data"]["next_cursor"]
    if not cursor:
        break

Response

"id": "crawl_01a12d2f-4c6c-7507-82b4-54a5a3035b81",
"type": "crawl",
"status": "queued",
"url": "https://hono.dev/docs",
"max_pages": 3,
"max_depth": 3,
"format": "markdown",
"mode": "normal",
"credits_per_page": 1,
"status_url": "https://api.scavio.dev/api/v1/extract/crawl/crawl_01a12d2f-4c6c-7507-82b4-54a5a3035b81"
},
"credits_used": 0
}
PreviousMap Website URLsNextCrawl Status and Results
ScavioScavio

One scraper API for every social, search, e-commerce and real estate platform. Built for AI agents.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative
  • Serper Alternative
  • Tavily vs Scavio
  • SerpAPI vs Scavio
  • All alternatives
  • Compare Scavio vs alternatives

Search APIs

  • Google Search API
  • Amazon Product API
  • YouTube API
  • Reddit API
  • Walmart Product API
  • TikTok API
  • Instagram API

Tools

  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy