# Documentation de l'API OpenScraper

*Page HTML : https://openscraper.ai/fr/docs · Index pour agents : https://openscraper.ai/llms.txt*

> Un seul endpoint REST exécute tous les scrapers. Authentifiez-vous avec une clé API, envoyez le module et ses paramètres, et récupérez des données structurées — en synchrone ou par polling.

## Introduction

Chaque scraper d'OpenScraper est piloté via une seule API HTTP. L'URL de base de toutes les requêtes est :

```text
https://api.openscraper.ai
```

Vous choisissez un module (par exemple le Web Unlocker ou le scraper Google Maps), passez ses paramètres, et l'API renvoie les lignes scrapées. Toutes les requêtes et réponses sont en JSON, et chaque requête doit être authentifiée.

## Authentification

Authentifiez-vous en envoyant votre clé API comme jeton Bearer dans l'en-tête `Authorization` :

```http
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
```

Créez et gérez vos clés depuis votre [tableau de bord](https://openscraper.ai/fr/dashboard). Une clé n'est affichée en entier **qu'une seule fois**, à sa création — conservez-la en lieu sûr. Les clés commencent par `sk_live_`.

Gardez votre clé API secrète. Elle débite votre compte — ne l'exposez jamais dans du code côté client, un dépôt public ou une requête navigateur.

## Démarrage rapide

Débloquez une page et récupérez son HTML en un seul appel synchrone :

```bash
curl -X POST https://api.openscraper.ai/runs \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "module": "unlocker_matrix",
    "params": { "url": "https://example.com", "geo": "France" },
    "sync": true
  }'
```

Avec `sync: true`, l'API attend la fin du scrape et renvoie le résultat dans la même réponse. Pour les gros travaux, soumettez en asynchrone et faites du polling (voir plus bas).

## MCP (Model Context Protocol)

La même API est aussi exposée sous forme de serveur MCP hébergé : un assistant IA (Claude sur claude.ai, Desktop ou Code, Cursor, ou tout client MCP) peut la piloter en langage naturel : sonder un site, estimer le prix, prévisualiser un échantillon, lancer le scrape et vous remettre les résultats. Mêmes modules, mêmes prix, mêmes crédits que l'API.

- URL du serveur : `https://mcp.openscraper.ai/mcp`
- Transport : Streamable HTTP

### Authentification

- **OAuth 2.1** (recommandé, pour claude.ai, les connecteurs Claude Desktop, Claude Code) : le client s'enregistre tout seul, vous vous connectez à OpenScraper et validez. Authorization code + PKCE (S256), enregistrement dynamique des clients, scope `mcp`. Les jetons d'accès durent 1 heure et se renouvellent automatiquement pendant 90 jours. Métadonnées : `https://mcp.openscraper.ai/.well-known/oauth-authorization-server`.
- **Clé API** : envoyez `Authorization: Bearer sk_live_...`, exactement comme pour l'API REST. Pour les autres clients, scripts et CI.

### Connecter un client

- **claude.ai** (et Claude Desktop et mobile, même compte) : Paramètres → Connecteurs → Ajouter un connecteur personnalisé, nommez-le « OpenScraper », collez l'URL, cliquez sur Se connecter et identifiez-vous.
- **Claude Code** : `claude mcp add --transport http openscraper https://mcp.openscraper.ai/mcp`, puis `/mcp` pour vous connecter. Avec une clé, ajoutez `-H "Authorization: Bearer sk_live_xxx"`.
- **Cursor et les clients qui acceptent une URL + des en-têtes** :

```json
{
  "mcpServers": {
    "openscraper": {
      "url": "https://mcp.openscraper.ai/mcp",
      "headers": { "Authorization": "Bearer sk_live_xxx" }
    }
  }
}
```

- **Clients stdio uniquement** (ex. le fichier de config de Claude Desktop), via `mcp-remote` (Node.js requis) :

```json
{
  "mcpServers": {
    "openscraper": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.openscraper.ai/mcp",
               "--header", "Authorization:${OPENSCRAPER_AUTH}"],
      "env": { "OPENSCRAPER_AUTH": "Bearer sk_live_xxx" }
    }
  }
}
```

### Outils

| Outil | Arguments | Description |
|---|---|---|
| `list_modules` | — | Scrapers dédiés disponibles (Google Maps, Leboncoin, Sitemap…). |
| `probe_site` | url | Accessibilité, anti-bot détecté, moteur qui passe, estimation du volume, recommandation de proxys. Facturé comme une petite sonde. |
| `estimate_cost` | module, params | Coût typique et plafond d'un run, en centimes. |
| `preview_sample` | module, params, n | Petit échantillon réel, synchrone, 25 lignes max. Facturé par élément. |
| `run_scrape` | module, params | Lance un run complet (async). Renvoie un task_id. |
| `get_run` | task_id | Statut, progression en direct et aperçu de 5 lignes. |
| `list_runs` | module? | Vos runs récents. |
| `cancel_run` | task_id | Arrête un run en gardant ce qui a été scrapé. |
| `export_results` | task_id, format | Lien de téléchargement de tous les résultats, xlsx (défaut) ou csv, valable 24 h. |
| `generate_client_code` | module, params, lang | Code prêt à lancer pour scraper depuis votre machine. |
| `warm_session` | url, proxy? | Session navigateur rejouable (cookies, user agent, profil TLS). |
| `find_emails` | urls | Emails de contact publiés par des sites web. |
| `verify_emails` | emails | Délivrabilité d'adresses email. |
| `get_balance` | — | Votre solde de crédits. |

### Déroulé type

1. `list_modules` ; si aucun scraper dédié ne convient, `probe_site`.
2. `estimate_cost`, puis `preview_sample`, validés avec l'utilisateur avant un gros run.
3. Soit `run_scrape` + `get_run` (on l'exécute), soit `generate_client_code` (vous l'exécutez).
4. `export_results` pour le jeu de données complet.

### Gros volumes de résultats

Les lignes ne transitent jamais en masse par la conversation : `get_run` affiche un aperçu de 5 lignes, et `export_results` renvoie un lien signé vers toutes les lignes en Excel ou CSV (sans connexion, valable 24 heures). Un agent avec un terminal peut télécharger le CSV et l'importer dans une base. Les crawls de sitemap s'exportent en JSON via `GET /runs/{id}/export.json`. En REST : `POST https://api.openscraper.ai/runs/{id}/export-link?format=csv` avec votre clé Bearer.

### Périmètre et facturation

Tout est limité au compte connecté : uniquement vos runs, facturés sur vos crédits aux tarifs habituels par élément (sondes et aperçus compris) ; un solde vide ne scrape rien. Guide pas à pas : https://openscraper.ai/fr/mcp. Exemple : https://openscraper.ai/fr/claude-leboncoin.

## Lancer un scrape

`POST /runs`

Champs du corps de la requête :

| Paramètre | Type | Requis | Défaut | Description |
| --- | --- | --- | --- | --- |
| `module` | string | oui | — | Le module à exécuter, ex. `"unlocker_matrix"` ou `"googlemaps_matrix"`. |
| `params` | object | oui | — | Paramètres propres au module (voir la référence de chaque module ci-dessous). |
| `sync` | boolean | non | `false` | Si `true`, attend le résultat en ligne. Si `false`, renvoie immédiatement un `task_id` à interroger. |
| `sync_timeout_seconds` | int | non | 1–600 | Secondes max d'attente quand `sync` vaut `true`. En cas de timeout, vous recevez un `task_id` et le statut `"running"`. |
| `webhook_url` | string | non | — | Optionnel. Une URL à notifier à la fin du run. |

**Synchrone** (`sync: true`) convient aux modules rapides à un seul résultat comme le Web Unlocker. **Asynchrone** (par défaut) convient aux modules qui renvoient beaucoup de lignes, comme Google Maps.

Le run est toujours facturé au propriétaire de la clé API.

## Récupérer les résultats

### Réponse synchrone

Quand le scrape se termine dans le délai imparti, vous recevez un HTTP 200 et l'objet run complet :

```json
{
  "id": "6f0b…",
  "module": "unlocker_matrix",
  "status": "done",
  "result": [
    {
      "url": "https://example.com",
      "status_code": 200,
      "content_type": "text/html",
      "result_url": "https://api.openscraper.ai/runs/6f0b…/file"
    }
  ],
  "error": null,
  "progress": { "scraped": 1, "credits_exhausted": false }
}
```

`result` est un tableau de lignes scrapées (les champs dépendent du module). `status` vaut `pending`, `running`, `done`, `error` ou `stopped`.

### Asynchrone et polling

Une soumission non-sync (ou un appel sync qui dépasse le délai) renvoie un `task_id` avec le statut `"pending"` ou `"running"` :

```json
{ "task_id": "6f0b…", "status": "pending" }
```

Interrogez le run jusqu'à un statut terminal :

```bash
curl https://api.openscraper.ai/runs/6f0b… \
  -H "Authorization: Bearer sk_live_xxx"
```

`GET /runs/{task_id}` renvoie le même objet run que ci-dessus. Interrogez toutes les quelques secondes jusqu'à ce que `status` soit `done`, `error` ou `stopped`. Pendant l'exécution, `progress.scraped` indique combien de lignes ont déjà été collectées.

## Erreurs

L'API utilise les codes HTTP standard :

| Statut | Signification | Description |
| --- | --- | --- |
| `200` | OK | Run synchrone terminé avec succès. |
| `202` | Accepted | Run accepté / en cours — interrogez avec le `task_id`. |
| `400` | Bad Request | Module inconnu ou paramètres mal formés. |
| `401` | Unauthorized | Clé API manquante ou invalide. |
| `403` | Forbidden | Module réservé aux comptes admin. |

Un run qui *démarre* mais échoue en cours arrive avec `status: "error"` et un message court dans le champ `error`. Les diagnostics détaillés au niveau des fournisseurs ne sont jamais renvoyés aux clients — ils sont disponibles dans votre tableau de bord.

## Crédits et facturation

La facturation est à l'usage : vous êtes facturé par élément réellement scrapé, débité au fil de l'exécution. Aucune réservation à l'avance.

Si votre solde ne couvre même pas un élément, le run renvoie immédiatement zéro résultat avec `progress.credits_exhausted: true`. Si les crédits s'épuisent en cours de route, le run s'arrête proprement et conserve tout ce qui a été scrapé — il se termine en `done`, pas en `error`.

Consultez les tarifs par module sur la [page Tarifs](https://openscraper.ai/fr/pricing).

## Référence module : Web Unlocker

`module: "unlocker_matrix"`

Récupérez n'importe quelle URL via notre stack anti-bot et obtenez le HTML brut. Renvoie exactement un résultat. À utiliser de préférence en synchrone.

| Paramètre | Type | Requis | Défaut | Description |
| --- | --- | --- | --- | --- |
| `url` | string | oui | — | L'URL cible à débloquer. |
| `geo` | string | non | `France` | Géolocalisation du proxy utilisée pour la requête. |
| `headless` | boolean | non | `true` | Exécute le JavaScript dans un navigateur headless avant de renvoyer le HTML. Désactivez pour une récupération HTTP brute et plus rapide. |

Champs du résultat :

| Champ | Type | Description |
| --- | --- | --- |
| `url` | string | L'URL récupérée. |
| `status_code` | int | Statut HTTP de la récupération distante. |
| `content_type` | string | Type MIME du corps renvoyé. |
| `result_url` | string | Une URL pour télécharger le HTML/corps brut de la page. |

Le corps de la page n'est pas inclus dans le JSON — récupérez-le depuis `result_url` (même auth Bearer).

## Référence module : Google Maps Search

`module: "googlemaps_matrix"`

Exportez tous les établissements d'une URL de recherche Google Maps — noms, adresses, téléphones, sites web, coordonnées, etc. Renvoie beaucoup de lignes ; exécutez-le en asynchrone.

| Paramètre | Type | Requis | Défaut | Description |
| --- | --- | --- | --- | --- |
| `url` | string | oui | — | Une URL de recherche Google Maps. |
| `max_results` | int | non | `200` | Google limite une recherche à ~200 résultats. |
| `collect_contacts` | boolean | non | `true` | Récupère aussi les contacts depuis le site web de chaque lieu. |
| `details` | boolean | non | `false` | Extrait des attributs supplémentaires (`plus_code`, horaires…). |
| `ratings` | string | non | `Any rating` | Filtre les lieux par note moyenne minimale. |
| `images` | boolean | non | `false` | Extrait jusqu'à 240 images par fiche. |
| `search_country` | string | non | `United States` | Contexte géographique de la recherche. |
| `language` | string | oui | `English (US)` | Langue des résultats renvoyés. |

Chaque ligne de résultat inclut `title`, `category_name`, `address`, `phone`, `website`, `lat`/`lng`, `place_id`, etc.

## Référence module : Google Maps Reviews

`module: "googlemapreviews_matrix"`

Collectez tous les avis d'une URL d'établissement Google Maps. Exécutez en asynchrone et faites du polling.

| Paramètre | Type | Requis | Défaut | Description |
| --- | --- | --- | --- | --- |
| `url` | string | oui | — | Une URL d'établissement Google Maps. |
| `sort_by` | string | non | `newest` | Ordre de tri des avis. `"newest"` collecte tous les avis. |
| `max_results` | int | non | — | Nombre max d'avis à collecter par établissement. |
| `hours_back` | int | non | — | Ne collecte que les avis des N dernières heures. |
| `language` | string | oui | `English (US)` | Langue des avis renvoyés. |

Chaque avis inclut `user_name`, `score`, `text`, `published_at` et la réponse du propriétaire.

## Référence module : Sitemap Scraper

`module: "sitemap_matrix"`

Parcourez les sitemaps d'un site et récupérez toutes les URLs qu'ils listent. Donnez une URL racine et le crawl lit `robots.txt`, puis suit tous les sitemaps déclarés par le site (ou les emplacements habituels s'il n'en déclare aucun), des index de sitemaps jusqu'aux pages. Renvoie beaucoup de lignes ; exécutez-le en asynchrone.

Passez plutôt une **URL de sitemap** (`https://example.com/sitemap-fr.xml`) et seul ce document est crawlé : pas de `robots.txt`, aucun autre sitemap du site — uniquement les pages qu'il liste, plus les sitemaps enfants s'il s'agit d'un index.

| Paramètre | Type | Requis | Défaut | Description |
| --- | --- | --- | --- | --- |
| `url` | string | oui | — | Une URL racine de site, ou une URL de sitemap unique pour ne crawler que celui-ci. |
| `crawl_timeout` | int | non | `60` | Budget pour l'ensemble du parcours, en secondes. Max 900 — augmentez-le pour les très gros sites. |
| `concurrency` | int | non | `15` | Sitemaps téléchargés en parallèle. Max 50. |
| `max_results` | int | non | `50000` | S'arrête après ce nombre d'URLs. Pas de plafond — ce qui arrête un très gros run, c'est `crawl_timeout`, le timeout de 300 s du worker, ou votre solde de crédits. |
| `use_residential` | boolean | non | `false` | Autorise les IPs résidentielles quand le site refuse nos IPs datacenter (403/429). Facturé 4x sur tout le run — le tarif par sitemap comme celui par URL. |

Champs du résultat :

| Champ | Type | Description |
| --- | --- | --- |
| `url` | string | L'URL de page trouvée — ou, sur une ligne d'erreur, le sitemap en échec. |
| `entry_type` | string | `"page"` pour une URL découverte, `"error"` pour un sitemap non récupérable ou illisible. |
| `sitemap_url` | string | Le sitemap dans lequel l'URL était listée. |
| `site` | string | Hôte du site crawlé. |
| `position` | int | Rang (base 0) de la page dans son propre sitemap. |
| `lastmod` | string | `<lastmod>` tel que publié par le sitemap (datetime W3C). `null` s'il n'est pas déclaré. |
| `changefreq` | string | `<changefreq>`, en minuscules : `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, `never`. `null` s'il n'est pas déclaré. |
| `priority` | float | `<priority>` tel que déclaré, 0.0-1.0. `null` s'il n'est pas déclaré. |
| `error` | string | Lignes d'erreur uniquement : la raison de l'échec, `error_status` portant le statut HTTP. |

`position`, `lastmod`, `changefreq` et `priority` sont toujours présents sur chaque ligne, et valent `null` quand le sitemap ne déclare rien (la plupart des sites n'en publient qu'une partie ; les sitemaps en texte brut aucun).

```bash
curl -X POST https://api.openscraper.ai/runs \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "module": "sitemap_matrix",
    "params": { "url": "https://www.mercedes-benz.com/", "max_results": 5000 },
    "sync": false
  }'
```

Un crawl peut renvoyer des centaines de milliers d'URLs : `result` sur le run n'en contient donc que la première tranche. Toutes les lignes sont conservées, et l'ensemble est streamé par un endpoint d'export — `shape=rows` pour un objet plat par URL, `shape=report` pour le document `{sitemaps_found, pages, errors}` du crawler :

```bash
curl "https://api.openscraper.ai/runs/TASK_ID/export.json?shape=rows" \
  -H "Authorization: Bearer sk_live_xxx"
```

## Autres modules

Parcourez tous les scrapers disponibles — avec un formulaire prêt à l'emploi et des snippets de code à copier-coller — dans le [catalogue](https://openscraper.ai/fr/catalog) et le [playground](https://openscraper.ai/fr/playground). Chaque page de module affiche le corps de requête exact pour ce scraper.
