Skip to main content

crw

Python SDK for CRW — the open-source web scraper built for AI agents.

New CRW integrations should use the native /v1 methods exposed by this SDK. If you are migrating Firecrawl v2 SDK code, use the engine's /v2 compatibility layer and validate the documented differences.

Quick start

pip install crw
export CRW_API_KEY=crw_live_...   # from https://fastcrw.com
from crw import CrwClient

client = CrwClient()  # reads CRW_API_KEY, defaults to https://api.fastcrw.com
page = client.scrape("https://example.com", formats=["markdown", "links"])

print(page["markdown"])  # page is a plain dict: markdown, links, metadata, ...
print(page["links"])     # list[str] of absolute URLs

Full reference: https://docs.fastcrw.com/sdk-reference/

Install

# One-line install (auto-detects OS & arch):
curl -fsSL https://fastcrw.com/install | sh

# npm (zero install):
npx crw-mcp

# Python:
pip install crw

# Cargo:
cargo install crw-mcp

# Docker:
docker run -i ghcr.io/fastcrw/crw crw-mcp

CLI Usage

After installing, you can use crw-mcp as an MCP server for any AI coding agent:

# Start the MCP stdio server
crw-mcp

# Add to Claude Code
claude mcp add crw -- npx crw-mcp

MCP client config (works with Cursor, Windsurf, Cline, Claude Desktop, etc.):

{
  "mcpServers": {
    "crw": {
      "command": "npx",
      "args": ["crw-mcp"]
    }
  }
}

SDK Usage

CRW is cloud-first. By default the client uses the managed cloud (api.fastcrw.com) — sign up for 1000 free credits (no payment, no monthly reset; GitHub/Google, ~10s) and set CRW_API_KEY. To self-host the engine locally instead, set CRW_LOCAL=1 (zero-config, no key).

from crw import CrwClient

# Cloud (default) — reads CRW_API_KEY from the environment:
client = CrwClient()
result = client.scrape("https://example.com")
print(result["markdown"])

# ...or pass the key explicitly:
client = CrwClient(api_key="crw_live_...")

# Self-hosted server:
client = CrwClient(api_url="http://localhost:3000")

# Local zero-config engine (no server, no key): run with CRW_LOCAL=1 in the env.

# Scrape with options:
result = client.scrape("https://example.com", formats=["markdown", "links"])
print(result["markdown"])
print(result["links"])

# Crawl a site:
job = client.crawl("https://example.com", max_depth=2, max_pages=10)
print(job["id"])

# Map all URLs on a site:
urls = client.map("https://example.com")
print(urls)
print(urls.sitemaps)  # sitemap URLs the engine read, [] if the site has none

Works in both modes. In subprocess mode the engine needs a search backend configured ([search].searxng_url or CRW_SEARCH__SEARXNG_URL); the managed cloud has one preconfigured.

from crw import CrwClient

client = CrwClient(api_key="YOUR_KEY")  # cloud (default)

# Basic search
results = client.search("web scraping tools 2026")

# Search with options
results = client.search(
    "AI news",
    limit=10,
    sources=["web", "news"],
    tbs="qdr:w",
)

# Search + scrape content
results = client.search(
    "python tutorials",
    scrape_options={"formats": ["markdown"]},
)

Note: If search isn't configured, the engine returns a clear search_disabled error.

Scrape options & structured (LLM) extraction

# Force the renderer, wait for JS, pin a renderer tier:
result = client.scrape("https://example.com", render_js=True, wait_for=1500, renderer="chrome")

# Structured extraction with a JSON Schema (adds the `json` format automatically).
# Requires an LLM provider configured on the engine.
result = client.scrape(
    "https://example.com",
    json_schema={"type": "object", "properties": {"title": {"type": "string"}}},
)
print(result["json"])

Parse a document (PDF → markdown / JSON)

Works in both modes.

# From a path:
doc = client.parse_file("invoice.pdf", formats=["markdown"])
print(doc["markdown"], doc["metadata"]["numPages"])

# From bytes, with structured extraction:
doc = client.parse_file(
    content=pdf_bytes,
    filename="invoice.pdf",
    json_schema={"type": "object", "properties": {"total": {"type": "number"}}},
)

Extract, batch, capabilities, change-tracking (HTTP mode)

These require api_url (a running server / cloud):

client = CrwClient(api_key="YOUR_KEY")  # cloud (default)

# Structured LLM extraction across URLs (async job, polled to completion).
# Returns a per-URL results array: [{url, status, data, error, llmUsage}]
results = client.extract(
    ["https://example.com"],
    schema={"type": "object", "properties": {"title": {"type": "string"}}},
)
for r in results:
    if r["status"] == "completed":
        print(r["url"], r["data"])

# Explicit typed lifecycle. start_extract always sends Prefer: respond-async.
accepted = client.start_extract(
    ["https://a.example", "https://b.example"],
    schema={"type": "object", "properties": {"title": {"type": "string"}}},
    basis=True,
)
status = client.get_extract(accepted["id"])
client.cancel_extract(accepted["id"])  # idempotent

# Scrape many URLs in one async batch:
pages = client.batch_scrape(["https://a.com", "https://b.com"], formats=["markdown"])

# Feature-detect the server:
caps = client.capabilities()

# Diff a page against a prior snapshot (stateless):
diff = client.change_tracking_diff(
    current={"markdown": "new content"},
    previous={"markdown": "old content"},
)

Data sources

Structured records from named public APIs (papers, packages, registries). Find a source, then call it with the options it lists:

page = client.find_data("packages")
# page["items"]: [{provider, capability, name, requiredOptions, optionalOptions, creditsCost, licence, ...}]
# Next page: client.find_data("packages", offset=page["nextOffset"])

result = client.get_data("depsdev", "package", {"system": "npm", "name": "react"})
print(result["data"], result["provenance"]["licence"])

A few sources run on your own machine rather than on the API. For those, get_data() starts a local crw-mcp (CRW_BINARY, PATH, or the verified download this package already uses) and calls it with your API URL and key. close() stops it. Data sources are not available with CRW_LOCAL=1.

Metadata

Release files for crw 0.41.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crw 0.41.0
File Size Uploaded Provenance Actions
crw-0.41.0.tar.gz 40.3 kB Without provenance Details for crw-0.41.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for crw 0.41.0
File Interpreter ABI Platform Actions
crw-0.41.0-py3-none-any.whl Python 3 none any Details for crw-0.41.0-py3-none-any.whl

Total release size: 70.4 kB

Release files / crw-0.41.0.tar.gz

Download URL crw-0.41.0.tar.gz
Size 40.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8581056f0919ef5f527f5a8f2bdc103536960669ca7c6ecdf409fcfd90d0a2b0
BLAKE2b-256 checksum
How to use checksums
f36c06284f76778117698218d020d08d2cf1f69ae6068b84c01ca4762971def6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / crw-0.41.0-py3-none-any.whl

Download URL crw-0.41.0-py3-none-any.whl
Size 30.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac3742ba9b2e771ea714ae2642edc512dc975fd2461ea5ebf8082cb2971a90f6
BLAKE2b-256 checksum
How to use checksums
30de265bcba56d9a1530c60bd5e64d2c8a443c48a1deb1cc4b91ed7553f936d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.16

Security for crw 0.41.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.41.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page