# 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.


Python library:

```python
# 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)
```

Cloud API:

```bash
# 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_..."
```

Cloud from Python:

```python
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`](https://crawl4ai.com/docs/scrape/) | the engine is picked per domain (cache → HTTP → browser); bot walls and proxies are handled |
| `crawler.arun_many(urls)` | [`POST /scrape/batch`](https://crawl4ai.com/docs/scrape-batch/) · [`/scrape/jobs`](https://crawl4ai.com/docs/scrape-jobs/) | results stream as they land; jobs run in the background for thousands of URLs |
| `LLMExtractionStrategy` / `JsonCssExtractionStrategy` | [`POST /extract`](https://crawl4ai.com/docs/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`](https://crawl4ai.com/docs/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 |

---
Source: https://crawl4ai.com/docs/library/
