Scrape
Scrapez une URL et transformez-la en données structurées prêtes pour les LLM.
Introduction
L’API scrape AnyCrawl convertit n’importe quelle page web en données structurées optimisées pour les grands modèles de langage (LLM). Elle prend en charge plusieurs moteurs de scraping (Cheerio, Playwright, Puppeteer) et produit divers formats : HTML, Markdown, JSON, etc.
Points clés : l’API renvoie les données immédiatement et de façon synchrone — pas de polling ni de webhooks. Elle traite les requêtes concurrentes en parallèle pour le scraping à grande échelle ; sur le service hébergé, le nombre de requêtes simultanées par clé API dépend de votre offre (voir Concurrence).
Fonctionnalités principales
- Multi-moteurs :
auto(sélection intelligente, défaut),cheerio(HTML statique, le plus rapide),playwright(rendu JS multi-navigateurs),puppeteer(rendu JS optimisé Chrome) - Optimisé pour les LLM : extraction et formatage automatiques ; génération Markdown pour faciliter le traitement par les LLM
- Proxy : configuration HTTP/HTTPS
- Gestion d’erreurs : mécanismes complets d’erreurs et de nouvelles tentatives
- Hautes performances : concurrence native avec file d’attente asynchrone
- Réponse immédiate : API synchrone — résultats instantanés sans polling
Point de terminaison de l’API
POST https://api.anycrawl.dev/v1/scrapeExemples d’utilisation
cURL
Scraping de base (moteur auto par défaut)
curl -X POST "https://api.anycrawl.dev/v1/scrape" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com"
}'Contenu dynamique avec Playwright
curl -X POST "https://api.anycrawl.dev/v1/scrape" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://spa-example.com",
"engine": "playwright"
}'Scraping avec proxy
curl -X POST "https://api.anycrawl.dev/v1/scrape" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"engine": "playwright",
"proxy": "http://proxy.example.com:8080"
}'Paramètres de requête
| Paramètre | Type | Obligatoire | Défaut | Description |
| ------------------- | ------------------------ | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| url | string | Oui | - | URL à scraper ; adresse HTTP/HTTPS valide |
| template_id | string | Non | - | ID du modèle pour ce scrape |
| variables | object | Non | - | Variables du modèle (si template_id) |
| engine | enum | Non | auto | Moteur : auto, cheerio, playwright, puppeteer |
| formats | array | Non | ["markdown"] | Formats : markdown, html, text, screenshot, screenshot@fullPage, rawHtml, json, summary, links |
| timeout | number | Non | 60000 | Délai en ms. Si omis : 120000 pour proxy=stealth / proxy=auto ; sinon 60000. |
| retry | boolean | Non | false | Réessayer en cas d’échec |
| max_age | number | Non | - | Durée de vie max du cache (ms). 0 ignore la lecture ; omis = défaut serveur |
| store_in_cache | boolean | Non | true | Écrire le cache de page pour ce scrape |
| wait_for | number | Non | - | Délai avant extraction (ms) ; navigateur ; priorité inférieure à wait_for_selector |
| wait_until | enum | Non | - | Condition d’attente : load, domcontentloaded, networkidle, commit |
| wait_for_selector | string, object, or array | Non | - | Attendre un ou plusieurs sélecteurs (navigateur). Chaîne CSS, objet { selector, state?, timeout? }, ou tableau. Séquentiel. Priorité sur wait_for. |
| include_tags | array | Non | - | Balises à inclure, ex. h1 |
| exclude_tags | array | Non | - | Balises à exclure, ex. h1 |
| only_main_content | boolean | Non | true | Contenu principal uniquement (include_tags prioritaire) |
| proxy | string (URI) | Non | - | Adresse du proxy : http://proxy:port ou https://proxy:port |
| json_options | json | Non | - | Options JSON, ex. {"schema": {}, "user_prompt": "..."} |
| extract_source | enum | Non | markdown | Source pour le JSON : markdown (défaut) ou html |
| ocr_options | boolean | Non | false | OCR pour images markdown uniquement. N’altère pas html/rawHtml. |
Comportement du cache
max_agecontrôle les lectures du cache.0force une actualisation.store_in_cache=falsedésactive l’écriture.- En cas de cache hit, la réponse inclut
cachedAtetmaxAge(ms).
Types de moteurs
Remarque : playwright et puppeteer peuvent utiliser Chromium, mais leurs rôles et capacités diffèrent.
auto (défaut)
- Cas d’usage : lorsque le meilleur moteur pour la page n’est pas évident
- Avantages : analyse la page et choisit le moteur optimal —
cheeriopour le statique,playwrightpour le JS lourd - Fonctionnement : requête HTTP légère d’abord ; passage à un moteur navigateur si le rendu JS est nécessaire
- Recommandé pour : usage général, bonnes perfs sans choix manuel
cheerio
- Cas d’usage : HTML statique
- Avantages : le plus rapide, faible consommation
- Limites : pas d’exécution JavaScript, pas de contenu dynamique
- Recommandé pour : articles, blogs, sites statiques
playwright
- Cas d’usage : sites modernes avec JS, tests multi-navigateurs
- Avantages : attentes automatiques robustes, bonne stabilité
- Limites : consommation plus élevée
- Recommandé pour : applications web complexes
puppeteer
- Avantages : intégration Chrome DevTools, métriques, exécution rapide
- Limites : pas d’architecture ARM
Formats de sortie
Vous pouvez indiquer les formats via formats :
markdown
- Description : HTML converti en Markdown propre et structuré
- Cas d’usage : traitement LLM, documentation, analyse
- Recommandé pour : texte dense, articles, blogs
html
- Description : HTML nettoyé et formaté
- Cas d’usage : structure HTML avec mise en forme
- Recommandé pour : contenu devant conserver la structure HTML
text
- Description : texte brut sans mise en forme
- Cas d’usage : extraction simple, analyse basique
- Recommandé pour : traitement texte uniquement, mots-clés
screenshot
- Description : capture de la zone visible
- Cas d’usage : représentation visuelle de la page
- Limites :
playwrightetpuppeteeruniquement - Recommandé pour : vérification visuelle, tests UI
screenshot@fullPage
- Description : capture pleine page (y compris sous la ligne de flottaison)
- Cas d’usage : vue complète de la page
- Limites :
playwrightetpuppeteeruniquement - Recommandé pour : documentation de page, archivage
rawHtml
- Description : HTML source brut non traité
- Cas d’usage : HTML exact tel que reçu
- Recommandé pour : analyse technique, débogage, structure d’origine
summary
- Description : résumé concis du contenu via IA
- Cas d’usage : compréhension rapide, résumés, digest
- Recommandé pour : veille, recherche, curation, abstracts
links
- Description : tous les liens (URL) de la page sous forme de tableau de chaînes
- Cas d’usage : découverte de liens, sitemap, préparation au crawl, analyse des liens
- Fonctionnalités : URLs relatives → absolues, déduplication, fragments retirés
- Recommandé pour : crawlers, structure du site, pages liées
Objet json_options
Le paramètre json_options accepte :
schema: schéma d’extractionuser_prompt: invite utilisateurschema_name: nom optionnel de la sortieschema_description: description optionnelle de la sortie
Exemple
{
"schema": {},
"user_prompt": "Extract the title and content of the page"
}ou
{
"schema": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"company_name": {
"type": "string"
},
"summary": {
"type": "string"
},
"is_open_source": {
"type": "boolean"
}
},
"required": ["company_name", "summary"]
},
"user_prompt": "Extract the company name, summary, and if it is open source"
}Format de réponse
Succès (HTTP 200)
Scraping réussi
{
"success": true,
"data": {
"url": "https://mock.httpstatus.io/200",
"status": "completed",
"jobId": "c9fb76c4-2d7b-41f9-9141-b9ec9af58b39",
"title": "",
"metadata": [
{
"name": "color-scheme",
"content": "light dark"
}
],
"html": "<html><head><meta name=\"color-scheme\" content=\"light dark\"></head><body><pre style=\"word-wrap: break-word; white-space: pre-wrap;\">200 OK</pre></body></html>",
"screenshot": "http://localhost:8080/v1/public/storage/file/screenshot-c9fb76c4-2d7b-41f9-9141-b9ec9af58b39.jpeg",
"timestamp": "2025-07-01T04:38:02.951Z"
}
}Réponse cache hit
{
"success": true,
"data": {
"url": "https://example.com",
"status": "completed",
"jobId": "c9fb76c4-2d7b-41f9-9141-b9ec9af58b39",
"cachedAt": "2026-02-08T12:34:56.000Z",
"maxAge": 172800000
}
}Réponses d’erreur
400 — Erreur de validation
{
"success": false,
"error": "Validation error",
"details": {
"issues": [
{
"field": "engine",
"message": "Invalid enum value. Expected 'auto' | 'playwright' | 'cheerio' | 'puppeteer', received 'invalid'",
"code": "invalid_enum_value"
}
],
"messages": [
"Invalid enum value. Expected 'auto' | 'playwright' | 'cheerio' | 'puppeteer', received 'invalid'"
]
}
}401 — Authentification
{
"success": false,
"error": "Invalid API key"
}403 — Fonctionnalité non disponible dans votre offre
Service hébergé uniquement. Renvoyé lorsqu’une requête utilise une fonctionnalité non incluse dans votre offre — actuellement proxy: "stealth", qui nécessite l’offre Hobby ou supérieure.
{
"success": false,
"error": "stealth_proxy_not_allowed",
"message": "Stealth proxy is not available on your plan. Upgrade to Hobby or above to use proxy: stealth."
}429 — Limite de concurrence atteinte
Service hébergé uniquement. Renvoyé lorsque la clé API a déjà autant de requêtes en cours que son offre le permet. Rien n’a été lancé et aucun crédit n’a été débité — réessayez dès que l’une de vos requêtes en cours se termine.
{
"success": false,
"error": "Concurrency limit reached",
"message": "Your plan allows 2 concurrent requests. Retry when an in-flight request finishes, or upgrade your plan.",
"limit": 2
}Échec du scraping
{
"success": false,
"error": "Scrape task failed",
"message": "Page is not available: 404 ",
"data": {
"url": "https://mock.httpstatus.io/404",
"status": "failed",
"type": "http_error",
"message": "Page is not available: 404 ",
"code": 404,
"metadata": [
{
"name": "color-scheme",
"content": "light dark"
}
],
"jobId": "34cd1d26-eb83-40ce-9d63-3be1a901f4a3",
"title": "",
"html": "<html><head><meta name=\"color-scheme\" content=\"light dark\"></head><body><pre style=\"word-wrap: break-word; white-space: pre-wrap;\">404 Not Found</pre></body></html>",
"screenshot": "screenshot-34cd1d26-eb83-40ce-9d63-3be1a901f4a3.jpeg",
"timestamp": "2025-07-01T04:36:20.978Z",
"statusCode": 404,
"statusMessage": ""
}
}ou
{
"success": false,
"error": "Scrape task failed",
"message": "Page is not available: 502 ",
"data": {
"url": "https://mock.httpstatus.io/502",
"status": "failed",
"type": "http_error",
"message": "Page is not available: 502 ",
"code": 502,
"metadata": [
{
"name": "color-scheme",
"content": "light dark"
}
],
"jobId": "5fc50008-07e0-4913-a6af-53b0b3e0214b",
"title": "",
"html": "<html><head><meta name=\"color-scheme\" content=\"light dark\"></head><body><pre style=\"word-wrap: break-word; white-space: pre-wrap;\">502 Bad Gateway</pre></body></html>",
"screenshot": "screenshot-5fc50008-07e0-4913-a6af-53b0b3e0214b.jpeg",
"timestamp": "2025-07-01T04:39:59.981Z",
"statusCode": 502,
"statusMessage": ""
}
}ou
{
"success": false,
"error": "Scrape task failed",
"message": "Page is not available: 400 ",
"data": {
"url": "https://mock.httpstatus.io/400",
"status": "failed",
"type": "http_error",
"message": "Page is not available: 400 ",
"code": 400,
"metadata": [
{
"name": "color-scheme",
"content": "light dark"
}
],
"jobId": "0081747c-1fc5-44f9-800c-e27b24b55a2c",
"title": "",
"html": "<html><head><meta name=\"color-scheme\" content=\"light dark\"></head><body><pre style=\"word-wrap: break-word; white-space: pre-wrap;\">400 Bad Request</pre></body></html>",
"screenshot": "screenshot-0081747c-1fc5-44f9-800c-e27b24b55a2c.jpeg",
"timestamp": "2025-07-01T04:38:24.136Z",
"statusCode": 400,
"statusMessage": ""
}
}ou
{
"success": false,
"error": "Scrape task failed",
"message": "Page is not available",
"data": {
"url": "https://httpstat.us/401",
"status": "failed",
"type": "http_error",
"message": "Page is not available"
}
}Bonnes pratiques
Choix du moteur
- Incertain / général →
auto(défaut) — le serveur choisit le moteur optimal - Sites statiques (actus, blogs, docs) →
cheerio - Applications complexes (SPA avec JS) →
playwrightoupuppeteer
Performance
- Pour beaucoup de contenu statique, privilégiez
cheerio - N’utilisez
playwrightoupuppeteerque si le rendu JS est nécessaire - Pour de meilleurs résultats : proxies rotatifs pour limiter blocages et débits ; proxies stables
- Envoyez vos requêtes en parallèle dans la limite de concurrence de votre offre — les requêtes au-delà sont rejetées avec
429au lieu d’être mises en file d’attente
Gestion d’erreurs
try {
const response = await fetch("/v1/scrape", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com" }),
});
const result = await response.json();
if (result.success && result.data.status === "completed") {
// Handle successful result
console.log(result.data.markdown);
} else {
// Handle scraping failure
console.error("Scraping failed:", result.data.error);
}
} catch (error) {
// Handle network error
console.error("Request failed:", error);
}Forte concurrence
L’API traite les requêtes concurrentes en parallèle.
- Service hébergé (anycrawl.dev) : chaque clé API ne peut exécuter qu’un nombre limité de requêtes simultanément, selon votre offre. Une requête au-delà de cette limite est immédiatement rejetée avec
429— réessayez-la dès que l’une de vos requêtes en cours se termine. - Auto-hébergé : aucune limite de concurrence par défaut.
Maintenez le nombre de requêtes parallèles dans la limite de votre offre :
// Concurrent scraping example
const urls = ["https://example1.com", "https://example2.com", "https://example3.com"];
const scrapePromises = urls.map((url) =>
fetch("/v1/scrape", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url, engine: "cheerio" }),
}).then((res) => res.json())
);
// All requests execute concurrently and return immediately
const results = await Promise.all(scrapePromises);Questions fréquentes
Quand utiliser quel moteur ?
Chaque moteur a ses avantages :
- Auto (défaut) : choix intelligent par URL — départ rapide avec Cheerio, passage à Playwright si JS nécessaire
- Cheerio : HTML statique, le plus rapide, pas de JS
- Playwright : apps complexes, stabilité et attentes ; davantage de navigateurs à l’avenir
- Puppeteer : Chrome/Chromium uniquement ; pas sur CPU ARM ; pas d’images Docker associées fournies
Pourquoi certains sites échouent ?
Raisons possibles :
- Le site bloque les crawlers (403/404)
- JS requis mais moteur
cheerio - Authentification ou en-têtes spéciaux requis
- Problèmes réseau
Sites avec connexion ?
L’API ne gère pas l’authentification utilisateur pour l’instant. Recommandations :
- Scraper les pages publiques
- Autres moyens pour le contenu authentifié
Configuration proxy ?
- Par défaut, un proxy de qualité est fourni. Sans besoin particulier, vous n’avez pas à configurer vous-même.
- Proxies HTTP/HTTPS pris en charge
- Format :
http://host:portouhttps://host:port - Proxies stables et disponibles
Limitation de débit pour les requêtes concurrentes ?
Sur le service hébergé, oui : chaque clé API ne peut exécuter qu’un nombre limité de requêtes simultanément, selon votre offre. Les requêtes au-delà de la limite renvoient immédiatement 429 Concurrency limit reached — réessayez dès qu’une requête en cours se termine. Les déploiements auto-hébergés n’ont pas de limite de concurrence par défaut.