From the library to the cloud
You already know crawl4ai. The cloud runs the same engine behind one key: no browser to install, no proxies to buy, no cookies to babysit. Each library call has one API call.
# one page → Markdown async with AsyncWebCrawler() as crawler: result = await crawler.arun("https://example.com") print(result.markdown) # many pages results = await crawler.arun_many(urls, config=run_conf) # typed JSON out of a page config = CrawlerRunConfig(extraction_strategy=LLMExtractionStrategy(schema=..., instruction=...)) result = await crawler.arun(url, config=config)
# one page → Markdown (POST /scrape) curl https://api.crawl4ai.com/scrape -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" -d '{"url": "https://example.com", "format": "md"}' # many pages, results stream as they land (POST /scrape/batch · /scrape/jobs for thousands) curl -N https://api.crawl4ai.com/scrape/batch -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" -d '{"urls": ["https://a.com", "https://b.com"], "format": "md"}' # typed JSON out of a page (POST /extract) curl https://api.crawl4ai.com/extract -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" -d '{"url": "https://example.com", "instruction": "the product name and price"}' # web search, which the library does not have (GET /search) curl "https://api.crawl4ai.com/search?q=web+scraping" -H "Authorization: Bearer sk_live_..."
import requests H = {"Authorization": "Bearer sk_live_..."} BASE = "https://api.crawl4ai.com" # one page → Markdown md = requests.post(BASE + "/scrape", json={"url": "https://example.com", "format": "md"}, headers=H).json()["markdown"] # typed JSON out of a page data = requests.post(BASE + "/extract", json={"url": url, "instruction": "the product name and price"}, headers=H).json() # web search hits = requests.get(BASE + "/search", params={"q": "web scraping"}, headers=H).json()["results"]
| in the library | in the cloud | what changes |
|---|---|---|
crawler.arun(url) |
POST /scrape |
the engine is picked per domain (cache → HTTP → browser); bot walls and proxies are handled |
crawler.arun_many(urls) |
POST /scrape/batch · /scrape/jobs |
results stream as they land; jobs run in the background for thousands of URLs |
LLMExtractionStrategy / JsonCssExtractionStrategy |
POST /extract |
a plain-English instruction or a JSON schema; no selectors to write |
PruningContentFilter → fit_markdown |
on by default | every scrape returns clean Markdown with the boilerplate stripped |
| (no web search) | GET /search |
ranked results as JSON, from our own search stack |
| your machine's browser, proxies, cookies | ours | three regions, routed to the nearest; the library stays open source, forever |
Something unclear or wrong on this page? Tell us.