Meilleure API Leboncoin pour scraper des données à grande échelle

Shehriar Awan
6 Aug 2026

44 min read

Leboncoin publie une vraie API REST, documentée... et elle cote des véhicules. Elle ne renvoie aucune annonce. Pour les données d'annonces, il te faut une API tierce. lobstr.io est celle qui tient à grande échelle, avec 6 endpoints Leboncoin. Piloterr est moins chère et synchrone, mais uniquement sur les données d'annonces.

⚡ Résumé en 30 secondes

  1. L'API officielle, c'est l'API Argus®, côté leboncoin auto. Elle cote les véhicules à la plaque. Pas d'endpoint de recherche, pas d'endpoint d'annonce, rien en dehors de l'auto... et même un compte de test exige un contrat annuel
  2. Le faire toi-même, ça meurt vite. Une des protections anti-bot les plus strictes d'Europe, activement maintenue. Et même en passant, tu paies des proxies résidentiels à vie
  3. lobstr.io (le meilleur choix global) ... tient à gros volume : 6 endpoints pour le scraping et l'automatisation, une fiabilité publiée scraper par scraper, 2 $ les 1 000 à grande échelle. Le hic : c'est asynchrone, et lent par worker
  4. Piloterr (la meilleure option sync) ... uniquement les données d'annonces, mais un seul GET les renvoie, 20 annonces/min, à partir de 5,44 $ les 1 000. Le hic : aucun numéro de téléphone, aucune réputation vendeur

Dis-moi juste laquelle choisir

API Argus® officielle lobstr.io Piloterr
Renvoie les données d'annonces
Type REST, OAuth 2.0 REST, async REST, sync
Accès Appel commercial + contrat annuel Self-service, 20 $/mois Self-service, 49 $/mois
Essai gratuit ❌ aucun palier gratuit ✅ 500 crédits, sans CB
Coût pour 1k annonces Non publié 8 $ → 2 $ 5,44 $ → 3,76 $
Numéros de téléphone vendeur seule source
Réputation vendeur
Endpoints Leboncoin Cote véhicule uniquement 6 crawlers 3 endpoints
Automatisation (messagerie)
Vitesse, un seul worker n/a 3-4 annonces/min 20 annonces/min
Rétention des données n/a 28 jours Aucune
Reprise après échec n/a ✅ met en pause, garde le partiel ❌ s'arrête net
Note utilisateurs n/a Capterra 5,0 (33) Capterra 4,8 (33)
Limite principale Ne fait pas les annonces Async, lent par worker Ni téléphone, ni réputation

Deux de ces trois colonnes sont de vraies options. Voici pourquoi la première n'en est pas une, et quoi faire à la place.

Leboncoin propose-t-il une API ?

Oui. Et presque tout le monde se trompe là-dessus, parce qu'on regarde leboncoin.fr, on ne trouve rien, et on s'arrête là.
Leboncoin publie l'API Argus® sur api.leboncoin.auto, avec une documentation publique sur developer.leboncoin.auto.
Leboncoin propose-t-il une API ?

C'est du vrai travail d'ingénierie : RESTful, OAuth 2.0, JSON:API, versionnée en 3.0 et 3.1, avec un catalogue d'erreurs, une spec YAML et un guide de migration depuis leur ancien webservice.

Et c'est aussi totalement inutile pour ce que tu veux faire.

Ce qu'elle fait vraiment

Le référentiel Argus® est une base de données de véhicules.

Dans les mots de Leboncoin, il sert à « décrire et définir rigoureusement un véhicule VN/VO par sa génération, sa motorisation, sa finition commerciale, son prix, ses caractéristiques », et il vise « constructeurs, loueurs, assureurs, concessionnaires, infomédiaires ».

Tu lui donnes une plaque d'immatriculation française. Il te renvoie le véhicule.

Domaine Endpoints
Auth POST /oauth/token
Identification par plaque POST /checkout/3.1/matchings · GET /checkout/3.1/matchings/{id} · /vehicle · /registration-card · /candidates · /order
Valeurs Argus® (cote) Cote actuelle, cote à date passée, cote stock, cote personnalisée, cotes avec frais professionnels
Valeur résiduelle POST /api/public/v1/residual-value

Obtenir un accès, c'est le premier mur

Ce n'est pas du self-service. Dans leur doc :
Obtenir un accès, c'est le premier mur

« Après analyse de votre besoin, notre service commercial prendra contact avec vous concernant la procédure à suivre. L'acquisition d'un compte test pour essayer nos API est également possible auprès de notre service commercial sous réserve de souscription à un contrat annuel. »

Relis la dernière clause. Même un compte de test demande de signer un contrat annuel. Un contrat annuel... pour essayer. 🙃

Les identifiants arrivent par un lien onetimesecret : un client_id et un client_secret. Les clients professionnels reçoivent en plus un identifiant et un mot de passe compte cote.

Authentification

OAuth 2.0, tokens valables 120 minutes. Deux types de grant, selon que tu as un compte cote ou non.

Requête

curl --location 'https://api.leboncoin.auto/oauth/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_id=VOTRE_CLIENT_ID_ICI' \ --data-urlencode 'client_secret=<client_secret>' \ --data-urlencode 'type=part'
f

Réponse

{ "access_token": "VOTRE_TOKEN", "token_type": "bearer", "expires_in": 7200, "created_at": 1495476696 }
f
expires_in: 7200 secondes, c'est exactement les 120 minutes promises par la doc. Le flow professionnel remplace par grant_type=password, ajoute username et password, et met type=pro.

Une vraie requête

Identification par plaque. Les requêtes utilisent JSON:API, donc le content type est application/vnd.api+json.

Requête

curl --location 'https://api.leboncoin.auto/checkout/3.1/matchings' \ --header 'Authorization: Bearer VOTRE_TOKEN' \ --header 'Content-Type: application/vnd.api+json' \ --data '{ "data": { "type": "matchings", "attributes": { "offer": "identification-by-registration", "registration": "dn386yt" } } }'
f
Tu récupères un 201 Created et une ressource matchings dont les relationships pointent vers la carte grise, le véhicule et les candidates... les modèles probables, classés par un score de popularité quote-ratio.

Ensuite tu vas chercher le détail.

Requête

GET /checkout/3.1/matchings/{id}?include=candidates,registration-card
Leur doc glisse ici un avertissement honnête sur les performances, et je l'ai apprécié : « L'utilisation de la variable include implique des requêtes complexes et donc plus lentes ».

Là où elle s'arrête

Si tu es concessionnaire, assureur ou loueur et que tu cotes des véhicules, c'est sincèrement le bon outil et tu devrais l'utiliser. Il est bien conçu et il fait son travail.

Mais il ne peut pas te dire ce qui est en ligne sur Leboncoin en ce moment. Pas d'endpoint de recherche. Pas d'endpoint d'annonce. Aucune donnée vendeur.

Pas d'immobilier, pas de mobilier, pas d'emploi, rien en dehors de l'auto. Et aucune limite de débit ni tarif publié nulle part, parce que les deux dépendent du contrat et n'apparaissent qu'une fois leur équipe commerciale engagée.

Donc la porte officielle existe, elle est verrouillée, et elle donne sur une autre pièce.

Quelles autres options a-t-on ?

Voilà la pensée qui vient à tout développeur juste après. Pas d'API ? Très bien. J'ouvre les DevTools, je trouve les endpoints internes et je leur parle directement. Ou alors j'écris un scraper... un peu de parsing HTML, un navigateur headless, plié d'ici vendredi.

Ça ne marche pas.

Quelles autres options a-t-on ?
C'est un 403 Forbidden sur une simple requête de page catégorie, et un défi « glisser pour vérifier ». Leboncoin liste ses propres déclencheurs sur cet écran, et le dernier est mon préféré : « Utilisation d'outils de développement ou d'inspection ».

Avoir les DevTools ouverts suffit à te faire repérer.

Et admettons que tu passes. Tu viens de signer pour trois coûts qui ne disparaîtront jamais :

  1. Des proxies résidentiels, en continu. Les IP de datacenter sont filtrées bien plus durement, et du trafic français est attendu
  2. De la maintenance permanente. Leboncoin déploie des changements sans prévenir et durcit sans arrêt sa couche anti-bot. Ton scraper ne casse jamais au moment où ça t'arrange
  3. Une difficulté qui grimpe avec le volume. Les techniques qui survivent à 100 annonces par jour s'effondrent à 100 000, donc le correctif n'est jamais terminé
Le cimetière est public. Le wrapper open source Leboncoin le plus populaire, tdurieux/leboncoin-api, est aujourd'hui marqué DEPRECATED sur GitHub, avec ses requêtes bloquées.
Quelles autres options a-t-on ?

Et il y a encore un mur derrière celui-là. La donnée que la plupart des gens veulent vraiment, le numéro de téléphone du vendeur, se cache derrière un login.

Et Leboncoin déconnecte les comptes de façon agressive dès que tu commences à tirer des numéros en volume.

C'est exactement pour ça que des API tierces dédiées existent. Pas comme un raccourci, mais parce que la maintenance est le produit.

Mais laquelle est la meilleure pour scraper à grande échelle ?

Meilleure API Leboncoin : lobstr.io

Note utilisateurs :Capterra 5,0 sur 33 avis, en août 2026
lobstr.io est une plateforme de scraping cloud no-code avec plus de 50 scrapers prêts à l'emploi, et sur Leboncoin elle propose la surface d'API la plus profonde de tout ce que j'ai testé.
Meilleure API Leboncoin : lobstr.io

Ce qu'elle propose

Six crawlers Leboncoin, chacun avec son endpoint, couvrant à la fois la collecte de données et l'automatisation.

# Crawler Ce qu'il fait
1 Listings Search Export Toutes les annonces d'une URL de recherche ou de catégorie
2 Listings & Phone Search Export Pareil, plus le vrai numéro du vendeur et son profil complet
3 Listing Scraper Des URL d'annonces précises que tu as déjà
4 Boutiques Scraper Les boutiques pro, avec SIREN, SIRET, adresse, horaires
5 Listing Status Checker Cette annonce est-elle toujours en ligne ?
6 Auto Message Sender Contacte les vendeurs via la messagerie de Leboncoin

Aucun autre fournisseur ne va au-delà de la recherche et du détail d'annonce. C'est la seule où le monitoring, les données d'entreprise B2B et la prise de contact sont des endpoints plutôt que des projets.

Fonctionnalités

  1. La seule API Leboncoin qui renvoie le vrai numéro de téléphone du vendeur
  2. Gestion multi-comptes, avec limites et temps de pause intégrés
  3. Fiabilité publiée, scraper par scraper
  4. Un dashboard no-code branché sur la même API
  5. Planification intégrée, donc aucun cron à maintenir
  6. Export vers CSV, Excel, JSON, JSONL, Google Sheets ou S3
  7. Une doc développeur avec des exemples exécutables, plus un SDK, un CLI et un serveur MCP
Le numéro de téléphone. Pas un booléen has_phone... le numéro lui-même, dans le même run que l'annonce, avec la date d'inscription, le taux de réponse, le délai de réponse, le nombre total d'annonces, les badges de vérification et le détail des évaluations.

Gestion multi-comptes. Connecte autant de comptes Leboncoin que nécessaire à un seul run, et quand l'un se fait déconnecter, il bascule tout seul sur le suivant.

Fonctionnalités

Des limites intelligentes et des temps de pause gardent tes comptes hors de la liste des bannis, et si tous les comptes lâchent, le run se met en pause au lieu de mourir.

Fonctionnalités

La stabilité est publiée, pas revendiquée. Chaque page produit de scraper affiche une section Built to run. avec un relevé en direct sur 90 jours.

Fonctionnalités

Le chiffre que je regarderais, ce n'est pas le pourcentage, c'est la colonne 100 % résolu sur les six. N'importe qui peut publier un taux de disponibilité.

Publier son nombre d'incidents et son délai médian de correction par scraper, c'est rare.

Voici le relevé complet de chaque scraper. Tu peux le vérifier en visitant la page produit de chacun.
Crawler Runs sans incident (90 j) Incidents Résolus Délai médian de correction
Listing Status Checker 99,78 % 60 100 % 19 min
Listings & Phone Search Export 99,74 % 751 100 % 42 min
Listing Scraper 99,73 % 3 100 % 100 min
Boutiques Scraper 99,64 % 5 100 % 133 min
Auto Message Sender 99,63 % 42 100 % 3 671 min
Listings Search Export 98,77 % 41 100 % 80 min

Ce relevé, c'est aussi ce sur quoi repose le calcul de débit.

Un seul Slot qui tourne 24h/24 sort environ 130 000 annonces par mois sans téléphone, ou 43 000 avec, et les Slots s'empilent : 20 par Squid, jusqu'à 100 par compte sur le plan le plus haut. Ça pousse un seul Squid au-delà de 2,6 M d'annonces par mois.

Le dashboard no-code. Ce n'est pas un produit séparé, c'est la même API avec une interface par-dessus. Un Squid créé en HTTP apparaît dans le dashboard, et un run lancé depuis le dashboard est lisible, modifiable et arrêtable via l'API.

Planification. Règle un Squid pour tourner toutes les heures, tous les jours ou toutes les semaines et il gère la cadence lui-même. Pas de cron, pas de worker à toi qui attend là pour déclencher une requête.

Fonctionnalités

Exports. Les résultats reviennent en CSV, Excel, JSON ou JSONL, et peuvent être poussés directement vers Google Sheets, S3, SFTP, e-mail ou un webhook.

Surface développeur. Un SDK Python (pip install lobstrio-sdk) avec clients sync et async, modèles typés et pagination automatique ; un CLI (pip install lobstrio) ; un serveur MCP pour la doc ; et des pages d'exemples par scraper avec du code exécutable pour les 50+ scrapers.
Fonctionnalités
Elle expose aussi un llms.txt et un llms-full.txt que tu peux donner directement à ton agent de code IA pour qu'il interagisse avec l'API.

Coût

Abonnement mensuel à base de crédits, sans frais de dépassement, et aucun palier gratuit. Tous les crawlers Leboncoin sont payants, donc le ticket d'entrée est à 20 $ par mois.

Coût
Plan Prix / mois Crédits Pour 1k crédits
Starter 20 $ 10 000 2,00 $
Pro 100 $ 100 000 1,00 $
Team 500 $ 1 000 000 0,50 $
Business 1 000 $ 2 000 000 0,50 $

Chaque crawler dépense ces crédits à son propre rythme, et le chiffre exact est dans la section de ce crawler plus bas.

Deux choses comptent plus que le prix affiché.

Tu es facturé au résultat, pas à la requête. Un appel qui revient vide ou en échec ne coûte rien. Piloterr facture chaque requête réussie, ce qui n'est pas la même chose... là-bas, un 200 qui porte une annonce maigre coûte quand même un crédit.

Les fonctions optionnelles se facturent aussi au succès. Si une annonce n'a pas de numéro, tu n'es pas facturé des 6 crédits pour avoir cherché. Pareil pour le profil vendeur, pareil pour chaque option.

Avantages et inconvénients

Avantages Inconvénients
Seule API à renvoyer le vrai numéro du vendeur, avec un profil vendeur complet à côté Chère à l'entrée (8 $/1k contre 5,44 $ chez Piloterr)
La bascule auto entre comptes survit aux déconnexions Leboncoin Lente par worker : 3-4 annonces/min, 1/min avec téléphone
6 endpoints, couvrant scraping et automatisation Async uniquement : pas de réponse dans une seule requête
La moins chère à grande échelle, 2 $/1k sans téléphone Aucun palier gratuit, donc l'évaluer coûte 20 $
Facturée uniquement sur les données renvoyées, fonctions au succès
Relevé de fiabilité publié par scraper
SDK Python, CLI, MCP et 5 cibles de livraison

Sur la lenteur : c'est délibéré. lobstr.io fait des pauses de 30 à 60 secondes entre les pages pour rester sous le radar de Leboncoin.

Comment utiliser l'API Leboncoin de lobstr.io

lobstr.io est asynchrone, donc avant que les endpoints aient du sens, il faut comprendre sa forme. Six étapes, dans l'ordre.

Crawler → Squid → Account → Task → Run → Result

Un crawler est un modèle de scraper. Un Squid est ton instance configurée de ce modèle. Les tasks sont les URL que tu lui donnes. Un run les exécute. Ensuite tu récupères les results.

Étape 1 : Crawler

Créer un Squid demande le hash du crawler, pas son slug, et rien ne te le dit tant que ça n'a pas échoué. Résous-le une bonne fois.

Requête

curl -X GET "https://api.lobstr.io/v1/crawlers" \ -H "Authorization: Token YOUR_API_KEY"
f
👉 Voir la doc : List crawlers

Ou évite l'aller-retour. Voici les six.

Crawler Slug du crawler ID du crawler
Listings Search Export leboncoin-iter-listings 33db1ca85160105eeb84d5aa51cfad10
Listings & Phone Search Export leboncoin-iter-listings-with-phone 7bc4acdb18f2b90fdd5eb42b8e8251e9
Listing Scraper leboncoin-listing-scraper 9eade2d2a693bd871851806650e7fb4e
Boutiques Scraper leboncoin-boutique c6e88128aef71c079e58f0518687e10c
Listing Status Checker leboncoin-listing-status-checker 0c60c33b95db65c86d5c9fc127b7b2aa
Auto Message Sender leboncoin-auto-message-sender fa9c988768a3d61f358916400f3c4b65
Il y a un deuxième appel à connaître, c'est params.

Requête

curl -X GET "https://api.lobstr.io/v1/crawlers/33db1ca85160105eeb84d5aa51cfad10/params" \ -H "Authorization: Token YOUR_API_KEY"
f

Il renvoie le format d'entrée accepté avec son regex de validation, chaque réglage que prend le crawler, et le coût en crédits de chaque fonction optionnelle. Tous les tableaux de paramètres de cet article viennent de là.

👉 Voir la doc : Get crawler parameters

Étape 2 : Squid

Créer, puis configurer.

Requête

curl -X POST "https://api.lobstr.io/v1/squids" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "crawler": "33db1ca85160105eeb84d5aa51cfad10", "name": "Leboncoin Paris apartments" }'
f

Réponse

{ "id": "b6c56d18cb0046949461ba9ca278e8ad", "object": "squid", "name": "Leboncoin Paris apartments" }
f
👉 Voir la doc : Create a Squid
Cet id, c'est ce que tous les appels suivants utilisent. Maintenant configure-le.

Requête

curl -X POST "https://api.lobstr.io/v1/squids/b6c56d18cb0046949461ba9ca278e8ad" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "concurrency": 1, "export_unique_results": true, "no_line_breaks": true, "params": { "max_pages": 5, "max_results": 500, "fetch_since": "7d" } }'
f
Ce deuxième appel n'est pas optionnel. Un Squid doit être configuré avant un run, même quand tous les paramètres que tu pourrais régler sont optionnels et que tu envoies un objet params vide.
👉 Voir la doc : Update a Squid

Étape 3 : Account, mais seulement pour trois des six

Saute complètement cette étape pour Listings Search Export, Boutiques et Status Checker. Elle est obligatoire pour Listings & Phone Search Export, Listing Scraper et Auto Message Sender.

Le chemin facile, c'est l'extension Chrome : synchronise ton compte Leboncoin, copie l'ID du compte depuis Dashboard → Accounts, et passe-le dans le tableau accounts du Squid. Un compte ou cinquante, c'est le même flux.

Via l'API, commence par demander ce qui est nécessaire.

Requête

curl -X GET "https://api.lobstr.io/v1/account_types" \ -H "Authorization: Token YOUR_API_KEY"
f

Réponse

{ "name": "leboncoin-sync", "domain": "Leboncoin", "baseurl": "https://auth.leboncoin.fr", "cookies": [ { "name": "__Secure-Login", "required": true } ], "params": { "messages": { "default": 5, "max": 30, "display": "Messages per day" }, "batch": { "default": 8, "max": 8, "display": "Messages per batch" }, "batch_hours": { "default": 1, "max": 2, "display": "Pause hours between batches" } } }
f
👉 Voir la doc : List account types

Un seul cookie obligatoire. Ensuite tu synchronises.

Requête

curl -X POST "https://api.lobstr.io/v1/accounts/cookies" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "leboncoin-sync", "cookies": { "__Secure-Login": "YOUR_COOKIE_VALUE" } }'
f
Les codes de statut vont de 100 créé, 120 synchronisation en cours, 200 synchronisé, et la réponse finale te rend un account_hash que tu passes au Squid.
👉 Voir la doc : Sync an account

Limites de compte

Ce bloc params, c'est la couche de protection du compte, et il gouverne spécifiquement l'Auto Message Sender. Leboncoin plafonne le volume de messages qu'un compte peut envoyer, donc lobstr.io le plafonne pour toi.
Limite Par défaut Max
Messages par jour 5 30
Messages par batch 8 8
Heures de pause entre batchs 1 2

Le plafond est donc de 30 messages par jour, envoyés par batchs de 8, avec jusqu'à 2 heures de pause entre les batchs.

messages est une fenêtre glissante de 24 heures, et non une remise à zéro quotidienne : « chaque message libère son créneau exactement 24 heures après son envoi, donc le run ne se met en pause que tant que la limite est atteinte et reprend automatiquement à mesure que les messages plus anciens expirent ».

Tu peux réduire ces valeurs. Tu ne peux pas dépasser le max, et tu ne devrais pas vouloir le faire.

Requête

curl -X POST "https://api.lobstr.io/v1/accounts" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "account": "YOUR_ACCOUNT_HASH", "type": "leboncoin-sync", "params": { "messages": 20, "batch": 8, "batch_hours": 2 } }'
f
👉 Voir la doc : Update account limits

Étape 4 : Task

Une task, c'est une URL, et un Squid en prend autant que tu veux lui en donner. Dix URL de recherche, dix tasks, un seul run.

Requête

curl -X POST "https://api.lobstr.io/v1/tasks" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "squid": "b6c56d18cb0046949461ba9ca278e8ad", "tasks": [ { "url": "https://www.leboncoin.fr/recherche?category=9&locations=Paris_75001" }, { "url": "https://www.leboncoin.fr/recherche?category=9&locations=Lyon_69002" }, { "url": "https://www.leboncoin.fr/recherche?category=9&locations=Bordeaux_33000" } ] }'
f
👉 Voir la doc : Add tasks
Tes URL sont déjà dans un tableur ? Saute complètement le JSON et envoie le fichier. Les en-têtes de colonnes correspondent aux clés de paramètres du crawler, donc une seule colonne url suffit.

Requête

curl -X POST "https://api.lobstr.io/v1/tasks/upload" \ -H "Authorization: Token YOUR_API_KEY" \ -F "file=@tasks.csv" \ -F "squid=b6c56d18cb0046949461ba9ca278e8ad"
f

Le TSV marche aussi, et c'est le choix le plus sûr pour des URL Leboncoin, parce que les URL de recherche sont pleines de virgules.

👉 Voir la doc : Upload tasks

Chaque crawler valide son entrée contre un regex, donc une URL mal formée échoue ici plutôt qu'en plein run.

Crawler URL acceptée
Listings Search Export .*leboncoin.fr.*
Listings & Phone Search Export .*leboncoin.fr.*
Listing Scraper ^https://www.leboncoin.fr/ad/.*
Boutiques Scraper .*leboncoin.fr/boutique.*
Listing Status Checker .*leboncoin.fr/ad/.*
Auto Message Sender ^http(.*)leboncoin(.*)
Listing Scraper est le plus strict : le préfixe complet
https://www.
est obligatoire.

Filtre d'abord sur Leboncoin, puis copie l'URL. Chaque paramètre de filtre est conservé.

Étape 5 : Run

Le lancement tient en un appel.

Requête

curl -X POST "https://api.lobstr.io/v1/runs" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "squid": "b6c56d18cb0046949461ba9ca278e8ad" }'
f
👉 Voir la doc : Start a run

Comme lobstr.io est asynchrone, ton job est en gros mis en file. Savoir quand il est terminé, c'est ça qui compte. Pour ça, tu peux interroger l'endpoint de stats du run.

Requête

curl -X GET "https://api.lobstr.io/v1/runs/300e9c5c127d421c90f431478d9a2cfb/stats" \ -H "Authorization: Token YOUR_API_KEY"
f

Réponse

{ "id": "300e9c5c127d421c90f431478d9a2cfb", "object": "run", "is_done": true, "percent_done": "100%", "eta": "∞", "duration": "0:00:15.175532", "total_tasks": 10, "total_tasks_done": 10, "total_tasks_left": 0, "total_results": 6 }
f
is_done: true, c'est ton feu vert pour le scrape. C'est le flag que ta boucle surveille, et percent_done, eta et total_tasks_left sont ce que tu affiches à un utilisateur pendant qu'il attend.
Un piège ici, et c'est le genre qui ressemble à un jeu de données vide plutôt qu'à un bug. is_done et export_done ne basculent pas au même moment. is_done veut dire que le scraping est fini ; export_done veut dire que le fichier de résultats est construit, et il arrive plus tard. Sors de ta boucle d'attente sur is_done seul et tu récupéreras une page vide.
GET /v1/runs/{id} porte les deux flags, plus credit_used pour rapprocher la dépense dans le même appel.
👉 Voir la doc : Get run stats

Étape 6 : Result

Deux façons de récupérer. Paginer le JSON, ou télécharger tout le run sous forme de fichier.

Tu peux récupérer les résultats en JSON avec l'endpoint results. Il collecte même les données partielles pour toi, tu peux continuer à l'interroger pour de nouveaux résultats.

Requête

curl -X GET "https://api.lobstr.io/v1/results?squid=b6c56d18cb0046949461ba9ca278e8ad&page=1&limit=50" \ -H "Authorization: Token YOUR_API_KEY"
f

Réponse

{ "total_results": 3, "limit": 50, "page": 1, "total_pages": 1, "data": [ { "...": "crawler-specific result objects" } ], "next": null, "previous": null }
f
Chaque crawler renvoie cette même enveloppe. Seul data[] change de forme.
👉 Voir la doc : Get results
Ou prends le fichier. L'endpoint de téléchargement te rend une URL signée temporaire, en CSV par défaut, et file_format la bascule en xlsx, json, jsonl.

Requête

curl -X GET "https://api.lobstr.io/v1/runs/300e9c5c127d421c90f431478d9a2cfb/download?file_format=xlsx" \ -H "Authorization: Token YOUR_API_KEY"
f

Réponse

{ "s3": "https://s3.eu-west-1.amazonaws.com/api.lobstr.io/temporary/..." }
f
Remplace xlsx par csv, json ou jsonl. L'URL expire vite, donc récupère-la et passe à la suite.
👉 Voir la doc : Download a run

Les résultats sont conservés 28 jours. Ce qui veut dire qu'ils restent sur le serveur de lobstr.io pendant 28 jours à partir du jour du run. Tu peux les télécharger à tout moment durant cette période.

Tu peux aussi automatiser l'export vers Amazon S3, Google Sheets, ou les recevoir en fichier csv par e-mail.

Un seul POST sur /v1/delivery et les résultats atterrissent où tu veux dès qu'un run se termine.

Requête

curl -X POST "https://api.lobstr.io/v1/delivery?squid=b6c56d18cb0046949461ba9ca278e8ad" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "email": "you@example.com", "notifications": true }'
f

Se passer complètement du polling

Si tu préfères être prévenu plutôt que demander, enregistre un webhook. Abonne-toi à run.done et la boucle de polling disparaît de ton code.

Requête

curl -X POST "https://api.lobstr.io/v1/delivery?squid=b6c56d18cb0046949461ba9ca278e8ad" \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "webhook_fields": { "url": "https://your-endpoint.com/lobstr", "is_active": true, "retry": true, "events": { "run.running": false, "run.paused": true, "run.done": true, "run.error": true } } }'
f
run.paused est celui qui vaut le coup sur Leboncoin. C'est l'événement qui se déclenche quand tous les comptes synchronisés ont été déconnectés.
👉 Voir la doc : Livraison par webhook

Limites de débit

Endpoint Limite
/v1/squids 120 req/min
/v1/tasks 90 req/min
/v1/runs 120 req/min
/v1/results 2 req/s
Tu n'as rien à coder en dur. Chaque réponse porte X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset, et un 429 ajoute Retry-After en secondes. Lis les en-têtes, ralentis en fonction du compteur restant, et tu ne verras jamais de 429.
👉 Voir la doc : Rate limiting

Passons aux six crawlers, dans l'ordre où tu les voudras. J'ajoute pour chacun une courte intro, un cas d'usage, les paramètres et un script d'exemple.

1. Listings Search Export

1. Listings Search Export

Celui-ci sert à collecter des données d'annonces en masse depuis n'importe quelle URL de recherche ou de catégorie Leboncoin. Tu peux t'en servir pour du monitoring de marché, du suivi de prix, de l'analyse de stock.

Paramètre Défaut Notes
max_pages 100 Maximum 100
max_results null S'arrête après N annonces
fetch_since null 24h, 7d, 2w, ou une date absolue
fetch_since_timezone null Dates absolues uniquement, ignoré en silence pour le relatif
online_shop false Ajoute l'URL de la boutique du vendeur, sans crédit supplémentaire
max_unique_results_per_run null Plafonne les lignes uniques par run

Coût

  1. 8,00 $ les 1 000 à l'entrée
  2. 2,00 $ les 1 000 à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par annonce 4 8,00 $ 2,00 $
online_shop 0 Gratuit Gratuit

Script complet

import requests, time API_KEY = "YOUR_API_KEY" BASE = "https://api.lobstr.io/v1" headers = {"Authorization": f"Token {API_KEY}"} squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "33db1ca85160105eeb84d5aa51cfad10", "name": "Leboncoin Paris apartments", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={ "export_unique_results": True, "params": {"max_pages": 5, "fetch_since": "7d"}, }) requests.post(f"{BASE}/tasks", headers=headers, json={ "squid": squid, "tasks": [{"url": "https://www.leboncoin.fr/recherche?category=9&locations=Paris_75001"}], }) run = requests.post(f"{BASE}/runs", headers=headers, json={"squid": squid}).json()["id"] # Attends le scrape, puis l'export. Ils ne finissent pas en même temps. while True: r = requests.get(f"{BASE}/runs/{run}", headers=headers).json() if r["is_done"] and r["export_done"]: break time.sleep(30) print(f"{r['credit_used']} credits used") results, page = [], 1 while True: batch = requests.get(f"{BASE}/results", headers=headers, params={"squid": squid, "page": page, "limit": 50}).json() rows = batch.get("data", []) if not rows: break results.extend(rows) page += 1 time.sleep(0.5) print(f"{len(results)} listings")
f

Un résultat porte 115 champs de données, j'ai gardé ici les plus intéressants.

Réponse

{ "ANNONCE ID": "3210370635", "TITLE": "4 pièces avec balcon sur parc proche transports", "PRICE": "390000", "PRICE PER SQUARE METER": "4875", "URL": "https://www.leboncoin.fr/ad/ventes_immobilieres/3210370635", "LAT": "48.91719", "LNG": "2.35385", "CITY": "Saint-Denis", "POSTAL CODE": "93210", "FIRST PUBLICATION DATE": "2026-06-04T14:25:11", "LAST PUBLICATION DATE": "2026-07-09T14:25:11", "HAS PHONE": "TRUE", "AREA": "80", "ROOM COUNT": "4", "DPE": "a", "GES": "a", "REAL ESTATE TYPE": "Appartement", "SELLER REGISTERED AT": "2016-12-15", "SELLER BADGES": "[\"Responsiveness2\", \"VerifiedPhoneNumber\"]" }
f
Deux champs à remarquer. LAST PUBLICATION DATE attrape les annonces republiées, ce qu'aucun autre fournisseur ne renvoie. Et HAS PHONE: TRUE sans champ PHONE à côté, c'est précisément le manque que le crawler suivant vient combler.

2. Listings & Phone Search Export

2. Listings & Phone Search Export

Celui-ci, c'est le même export de recherche, plus le vrai numéro de téléphone du vendeur et un profil vendeur complet. Tu peux t'en servir pour de la génération de leads, de la prise de contact vendeur, la construction de listes de prospects joignables.

Il a besoin d'un compte Leboncoin synchronisé.

Paramètre Défaut Notes
functions.get_phone_numbers true Le numéro de téléphone lui-même
functions.get_seller_profile false Date d'inscription, taux de réponse, badges, évaluations
max_pages 99 Maximum 99, pas 100
max_results null S'arrête après N annonces
fetch_since null 24h, 7d, 2w, ou une date absolue
online_shop false Ajoute l'URL de la boutique du vendeur, sans crédit supplémentaire

Coût

  1. Annonces seules : 8,00 $ les 1 000 à l'entrée, 2,00 $ à grande échelle
  2. Avec téléphone (le défaut) : 20,00 $ les 1 000 à l'entrée, 5,00 $ à grande échelle
  3. Avec téléphone et profil vendeur : 28,00 $ les 1 000 à l'entrée, 7,00 $ à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par annonce 4 8,00 $ 2,00 $
get_phone_numbers, par numéro renvoyé 6 12,00 $ 3,00 $
get_seller_profile, par profil renvoyé 4 8,00 $ 2,00 $
online_shop 0 Gratuit Gratuit

Les fonctions se facturent au succès. Une annonce sans numéro à trouver coûte 4 crédits, pas 10.

Script complet

accounts = requests.get(f"{BASE}/accounts", headers=headers).json()["data"] account = next(a["id"] for a in accounts if a["type"] == "leboncoin-sync" and str(a["status"]) == "200") squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "7bc4acdb18f2b90fdd5eb42b8e8251e9", "name": "Leboncoin leads", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={ "accounts": [account], "params": { "max_pages": 99, "fetch_since": "7d", "functions": { "get_phone_numbers": True, "get_seller_profile": True, }, }, })
f
Les tasks, le run et les résultats sont identiques au crawler 1. Seuls la récupération du compte et le bloc functions sont nouveaux.

Il collecte toutes les données du Leboncoin Search Export + les données supplémentaires suivantes.

Réponse

{ "ANNONCE ID": "3210370635", "HAS PHONE": "TRUE", "IS MOBILE": "TRUE", "PHONE": "+336XXXXXXXX", "SELLER REGISTERED AT": "2016-12-15", "SELLER TOTAL ADS": "2", "SELLER BADGES": "[\"Responsiveness2\", \"VerifiedPhoneNumber\"]", "PARAM GET PHONE NUMBERS": "TRUE", "PARAM GET SELLER PROFILE": "TRUE" }
f
Ce champ PHONE, c'est toute la raison d'être de ce crawler, et c'est la seule chose qu'aucun concurrent ne renvoie, à aucun prix.

3. Listing Scraper

3. Listing Scraper

Celui-ci sert à scraper des URL d'annonces que tu as déjà, plutôt qu'à en découvrir de nouvelles.

Tu peux t'en servir pour enrichir une liste d'annonces existante, revérifier les prix sur des annonces connues, récupérer les numéros d'une shortlist.

Il a besoin d'un compte Leboncoin synchronisé, et le format d'URL est strict : le préfixe complet
https://www.leboncoin.fr/ad/...
est obligatoire.
Paramètre Défaut Notes
functions.get_phone_numbers true Le numéro de téléphone lui-même
C'est toute la surface de paramètres. Pas de max_pages, pas de filtre de date ... une URL en entrée, une ligne en sortie.

Coût

  1. Annonces seules : 8,00 $ les 1 000 à l'entrée, 2,00 $ à grande échelle
  2. Avec téléphone (le défaut) : 20,00 $ les 1 000 à l'entrée, 5,00 $ à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par annonce 4 8,00 $ 2,00 $
get_phone_numbers, par numéro renvoyé 6 12,00 $ 3,00 $

Script complet

squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "9eade2d2a693bd871851806650e7fb4e", "name": "Leboncoin listing enrichment", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={ "accounts": [account], "params": {"functions": {"get_phone_numbers": True}}, }) requests.post(f"{BASE}/tasks", headers=headers, json={ "squid": squid, "tasks": [ {"url": "https://www.leboncoin.fr/ad/ventes_immobilieres/3138320858"}, {"url": "https://www.leboncoin.fr/ad/voitures/3172676206"}, ], }) requests.post(f"{BASE}/runs", headers=headers, json={"squid": squid})
f

Réponse

{ "annonce_id": "3138320858", "title": "Appartement 6 pièces 212 m²", "url": "https://www.leboncoin.fr/ad/ventes_immobilieres/3138320858", "price": 3490000, "has_phone": true, "phone": "+331XXXXXXXX", "owner_name": "Junot Passy", "owner_type": "pro", "store_id": "84291829", "functions": { "get_phone_numbers": { "filling_date": "08/06/2026, 18:24:30 +0200" } }, "scraping_time": "2026-08-06T16:24:30.994Z" }
f

Ne suppose pas que ça reflète les exports de recherche. C'est 18 champs contre 115 : pas de coordonnées, pas d'attributs, pas de DPE, pas d'images. Tu récupères le noyau d'identité ... titre, prix, description, téléphone, vendeur. S'il te faut les attributs et la géoloc, pointe plutôt l'export de recherche sur une URL.

Un piège sur les dates. scraping_time est en ISO 8601 UTC, filling_date est en MM/DD/YYYY avec un décalage local. Les deux désignent le même instant, mais 08/06/2026 se lit 8 juin pour un parseur européen et 6 août pour un américain, et c'est un jeu de données français.

4. Boutiques Scraper

4. Boutiques Scraper

Celui-ci sert à collecter les boutiques des vendeurs professionnels, avec leur identité légale attachée.

Tu peux t'en servir pour de la prospection B2B, de la cartographie de concurrents, pour rapprocher les vendeurs Leboncoin des registres d'entreprises français.

Aucun compte nécessaire.

Paramètre Défaut Notes
functions.get_details true SIREN, SIRET, adresse, horaires, notes
functions.get_phone_numbers true Le numéro de la boutique, aucun compte requis
max_pages 99 Maximum 99
max_results null S'arrête après N boutiques
max_unique_results_per_run null Plafonne les lignes uniques par run

Coût

  1. Boutiques seules : 2,00 $ les 1 000 à l'entrée, 0,50 $ à grande échelle
  2. Avec détails : 6,00 $ les 1 000 à l'entrée, 1,50 $ à grande échelle
  3. Avec détails et téléphone (le défaut) : 18,00 $ les 1 000 à l'entrée, 4,50 $ à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par boutique 1 2,00 $ 0,50 $
get_details, par boutique enrichie 2 4,00 $ 1,00 $
get_phone_numbers, par numéro renvoyé 6 12,00 $ 3,00 $
Les deux fonctions sont à true par défaut, donc un Squid laissé tel quel facture 9 crédits par boutique. Mets-les à false si tu ne veux que la liste des boutiques.

Script complet

squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "c6e88128aef71c079e58f0518687e10c", "name": "Leboncoin boutiques", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={ "params": { "max_pages": 99, "functions": {"get_details": True, "get_phone_numbers": True}, }, }) requests.post(f"{BASE}/tasks", headers=headers, json={ "squid": squid, "tasks": [{"url": "https://www.leboncoin.fr/boutique/4308883"}], }) requests.post(f"{BASE}/runs", headers=headers, json={"squid": squid})
f

Réponse

{ "online_store_name": "007 agent i - Agence immobilière à Montmélian", "slogan": "007 AGENT-i : l'agence qui sort du lot", "siren": "902063700", "siret": "90206370000022", "sector": "property", "active_since": "2021-11-02T23:00:00Z", "address": "12 avenue de Savoie", "city": "Montmélian", "zipcode": "73800", "department_label": "Savoie", "lat": 45.50108, "lng": 6.05071, "has_phone": true, "phone": "04XXXXXXXX", "opening_hours": "Du lundi au vendredi, de 9h à 12h et de 14h à 18h.", "rating_value": 4.9, "rating_count": 152, "functions": { "get_details": { "filling_date": "08/06/2026, 18:29:57 +0200" }, "get_phone_numbers": { "filling_date": "08/06/2026, 18:30:44 +0200" } } }
f
siren et siret sont ceux qui comptent. Ce sont les numéros d'immatriculation d'entreprise français, et ce sont les clés de jointure vers Sirene, Pappers et Infogreffe, ce qui transforme un nom de boutique scrapé en fiche entreprise avec forme juridique, dépôts de comptes et données financières.

La suite offre donc deux voies de génération de leads. Les exports de recherche, c'est du B2C : vendeurs particuliers, numéros, réputation. Boutiques, c'est du B2B : entreprises immatriculées, identifiants d'entreprise, adresses physiques.

5. Listing Status Checker

5. Listing Status Checker

Celui-ci sert à vérifier si une annonce est toujours en ligne. Tu peux t'en servir pour du monitoring de stock, mesurer le délai de vente, nettoyer les lignes mortes d'une base que tu as constituée plus tôt.

Aucun compte nécessaire, et c'est ce qu'il y a de moins cher dans la suite.

Paramètre Défaut Notes
max_unique_results_per_run null Plafonne les lignes uniques par run

Coût

  1. Vérifications de statut : 2,00 $ les 1 000 à l'entrée
  2. 0,50 $ les 1 000 à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par vérification 1 2,00 $ 0,50 $

Script complet

squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "0c60c33b95db65c86d5c9fc127b7b2aa", "name": "Leboncoin listing monitor", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={"params": {}}) requests.post(f"{BASE}/tasks", headers=headers, json={ "squid": squid, "tasks": [{"url": u} for u in listing_urls], }) requests.post(f"{BASE}/runs", headers=headers, json={"squid": squid})
f

Réponse : annonce en ligne

{ "url": "https://www.leboncoin.fr/ad/ventes_immobilieres/3138320858", "status": "active", "status_code": 200, "functions": null, "scraping_time": "2026-08-06T16:27:08.544Z" }
f

Et quand l'annonce a disparu.

Réponse : annonce supprimée

{ "url": "https://www.leboncoin.fr/ad/voitures/3172676206", "status": "deactivated", "status_code": 410, "functions": null }
f
status status_code
active 200
deactivated 410
Branche-toi sur le nombre, pas sur la chaîne. 410 Gone plutôt que 404 Not Found, c'est le bon choix : 404 veut dire « ça n'existe pas », 410 veut dire « ça existait et ça a été supprimé ».

Rien ici n'est une donnée personnelle. Pas de nom de vendeur, pas de numéro, pas d'ID de propriétaire, donc tu peux surveiller des dizaines de milliers d'annonces indéfiniment et ne lancer les crawlers coûteux que sur celles qui bougent.

Un petit piège : les résultats portent url mais pas annonce_id, donc rejoindre une table d'annonces suppose d'extraire l'ID depuis l'URL.

6. Auto Message Sender

6. Auto Message Sender

Celui-ci sert à contacter les vendeurs via la messagerie de Leboncoin. Tu peux t'en servir pour sourcer du stock, contacter des vendeurs particuliers en volume, relancer après une recherche filtrée.

Il a besoin d'un compte Leboncoin synchronisé. Il prend une URL de recherche plutôt qu'une URL d'annonce, donc une seule task peut piloter toute une campagne.

Paramètre Défaut Notes
message Un modèle en français Obligatoire. Accepte #PSEUDO# et #TITLE#
fetch_since null 24h, 7d, 2w, ou une date absolue
hours_back null Même idée, exprimée en heures
max_results null S'arrête après N messages
max_unique_results_per_run null Plafonne les lignes uniques par run
Pas de max_pages ici. Le volume est gouverné par les limites de compte de l'étape 3, pas par les params du Squid.

Coût

  1. 40,00 $ les 1 000 messages à l'entrée
  2. 10,00 $ les 1 000 à grande échelle
Fonction Crédits Les 1 000 en Starter Les 1 000 en Team
Base, par message envoyé 20 40,00 $ 10,00 $

Les 1 000, c'est l'arithmétique, pas le plan. Au plafond de 30 messages par jour, un compte synchronisé culmine autour de 900 messages par mois, donc 1 000 messages veut dire plus de comptes, pas un plan plus gros.

Script complet

squid = requests.post(f"{BASE}/squids", headers=headers, json={ "crawler": "fa9c988768a3d61f358916400f3c4b65", "name": "Leboncoin outreach", }).json()["id"] requests.post(f"{BASE}/squids/{squid}", headers=headers, json={ "accounts": [account], "params": { "message": ( "Bonjour #PSEUDO#,\n\n" "Votre annonce #TITLE# m'intéresse. " "Est-elle toujours disponible ?\n\nMerci !" ), "fetch_since": "24h", "max_results": 20, }, }) requests.post(f"{BASE}/tasks", headers=headers, json={ "squid": squid, "tasks": [{"url": "https://www.leboncoin.fr/recherche?category=9&locations=Paris_75001"}], }) # Vérifie ton message et tes limites de compte avant cette ligne requests.post(f"{BASE}/runs", headers=headers, json={"squid": squid})
f

Réponse

{ "annonce_id": "3180087828", "url": "https://www.leboncoin.fr/ad/locations/3180087828", "message": "Hello [SELLER NAME],\n\nJe viens de voir votre article qui porte le nom:\nMaison 4 pièces 90 m²\n\nL'offre m'intéresse?\n...", "is_sent": true, "was_already_sent": true, "is_deactivated": false }
f
was_already_sent est le garde-fou. Il garde la trace de qui a été contacté et ne renverra pas de message sur la même annonce.

Ou saute tout ça

Tout ce qui précède, c'est l'API brute, et ça vaut le coup de la connaître parce que c'est ce que ton code de production appellera. Pour poser un jeu de données sur ton disque cet après-midi, il y a un chemin plus court.

Le CLI ramène les six étapes à une ligne.

pip install lobstrio lobstr go leboncoin-iter-listings \ "https://www.leboncoin.fr/recherche?category=9&locations=Paris_75001" \ -o listings.csv
f
Ça crée le Squid, le configure, ajoute la task, lance le run, attend avec une barre de progression en direct, et écrit le CSV. Ajoute --param max_results=200, passe plusieurs URL d'un coup, ou utilise --no-download pour lancer sans attendre.

Il y a aussi un mode pas à pas, si tu préfères piloter chaque étape toi-même.

lobstr crawlers search leboncoin lobstr squid create leboncoin-boutique --name "Boutiques FR" lobstr task add SQUID_ID "https://www.leboncoin.fr/boutique/4308883" lobstr run start SQUID_ID --wait lobstr results get SQUID_ID --format csv -o boutiques.csv
f
La livraison est là aussi, donc lobstr delivery s3 SQUID_ID --bucket my-bucket met en place l'export automatisé sans toucher à l'API.

Le SDK Python est celui à sortir quand le scraper vit à l'intérieur d'une application.

pip install lobstrio-sdk export LOBSTR_TOKEN=your_api_key
f
from lobstrio import LobstrClient client = LobstrClient() crawler = next(c for c in client.crawlers.list() if c.slug == "leboncoin-iter-listings") squid = client.squids.create(crawler=crawler.id, name="Paris apartments") client.squids.update(squid.id, params={"max_pages": 5, "fetch_since": "7d"}) client.tasks.add(squid=squid.id, tasks=[ {"url": "https://www.leboncoin.fr/recherche?category=9&locations=Paris_75001"} ]) run = client.runs.start(squid=squid.id) run = client.runs.wait(run.id, callback=lambda s: print(s.percent_done, s.eta)) print(f"{run.total_results} results, {run.credit_used} credits") for listing in client.results.iter(squid=squid.id): print(listing["TITLE"], listing["PRICE"])
f
runs.wait() remplace la boucle de polling, et results.iter() remplace la boucle de pagination. Il existe un AsyncLobstrClient avec la même surface si tu es dans une application asynchrone.
Un avertissement tiré de leur propre doc, et c'est bien qu'il soit publié : si LOBSTR_TOKEN n'est pas défini, le SDK retombe sur le fichier de config du CLI dans ~/.config/lobstr/config.toml, qui peut appartenir à un autre compte. Et il le fait en silence. Définis la variable explicitement en production.
👉 Voir la doc : CLI · SDK Python

Le problème : c'est une API asynchrone

Tout ce qui précède partage une même forme. Tu soumets le travail, tu attends, tu récupères. Ça va très bien pour 100 000 annonces sur une planification. C'est inutile quand un utilisateur est devant un formulaire à attendre une réponse.

Si c'est ta situation, aucune richesse de données ne réglera le problème. Il te faut un autre type d'API.

Synchrone vs asynchrone

Synchrone vs asynchrone

Une API synchrone renvoie les données dans la même réponse. Une requête en entrée, un résultat en sortie, rien à suivre.

Une API asynchrone renvoie un identifiant de job à la place. Le travail tourne sur l'infrastructure du fournisseur et tu récupères les résultats plus tard, par polling ou webhook.

Synchrone Asynchrone
Ce que tu récupères Les données Un identifiant de job
Quand Dans la même réponse Plus tard, par polling ou webhook
Qui gère la concurrence Toi Le fournisseur
Qui gère les retries Toi Le fournisseur
Qui gère le rythme anti-ban Toi Le fournisseur
État à suivre Aucun ID de job, statut de run, curseurs
Jobs en masse Tu orchestres Natif dans la conception
Portée d'un échec Une requête, tu la relances Le run se met en pause, le partiel est gardé
Jobs longs Bornés par les timeouts de requête Tournent des heures ou des jours
Tient derrière une UI en direct

Utilise une API sync si

  1. Un utilisateur attend la réponse
  2. Tu enrichis un seul enregistrement à la demande
  3. Ton volume est modeste
  4. Tu as déjà un ordonnanceur de jobs et tu veux que l'API reste un simple appel de fonction

Utilise une API async si

  1. Le job porte sur des milliers ou des millions d'enregistrements
  2. Il tourne sans surveillance, sur une planification
  3. Il tourne assez longtemps pour qu'un timeout de requête le tue
  4. Tout perdre en plein run est inacceptable

La conception asynchrone de lobstr.io est exactement ce qui lui permet de survivre à Leboncoin en volume, et exactement ce qui l'empêche de tenir derrière une recherche en direct. Si c'est ta situation, Piloterr est la réponse.

Meilleure API Leboncoin sync : Piloterr

Note utilisateurs :Capterra 4,8 sur 33 avis, en août 2026
Meilleure API Leboncoin sync : Piloterr
Piloterr est un fournisseur de scraping API-first fondé en 2021 et basé à Toulouse. Il y a un dashboard, mais aucun moyen no-code de lancer un scrape. Leboncoin se présente sous forme d'endpoints REST et d'un serveur MCP, et tu le câbles dans ton propre code.

Ce qu'elle propose

Trois endpoints, un crédit chacun, authentifiés avec x-api-key.
Endpoint Entrée Renvoie
GET /v2/leboncoin/search URL de recherche ou de catégorie ads[], total, pagination
GET /v2/leboncoin/ad ID d'annonce ou URL complète Le détail complet de l'annonce
POST /v2/leboncoin/search_api Filtres structurés ads[] plus les totaux pro/particuliers
Je n'ai pas aimé le troisième. Il renvoyait des erreurs 500 plus souvent que les deux autres, et il renvoyait des données qui ne correspondaient pas à la recherche Leboncoin en direct pour les mêmes filtres.
Utilise plutôt /search avec une vraie URL Leboncoin : filtre sur le site, copie l'URL, passe-la.

Fonctionnalités

  1. Vraiment synchrone, un GET et les données sont dans la réponse
  2. Le worker unique le plus rapide que j'ai mesuré, à 20 annonces par minute
  3. Les données géo et image les plus riches de tout ce que j'ai testé
  4. Des libellés français sur chaque attribut
  5. Un serveur MCP d'exécution

Vraiment synchrone. Un GET, les données dans la réponse, rien à interroger. C'est toute la raison de la choisir, et c'est la seule chose que lobstr.io ne peut pas faire, à aucun prix.

Vitesse. 20 annonces par minute contre 3 à 4 pour lobstr.io. Sur quelques milliers d'enregistrements, cet écart décide de ton après-midi.

Géo et images. Géométrie GeoJSON complète, et toutes les tailles d'image, de la vignette au grand format. lobstr.io renvoie les coordonnées et une image principale, donc pour une carte ou une galerie, c'est le meilleur payload.

Libellés français. Chaque attribut porte un key_label et un value_label, donc type_real_estate_sale: ancien arrive aussi comme « Type de vente : Ancien ». Utile quand la donnée finit devant des utilisateurs français.
MCP d'exécution. Chaque outil correspond à une opération de l'API, donc un agent peut réellement lancer des scrapes. Le MCP de lobstr.io est uniquement documentaire. Les deux publient llms.txt et llms-full.txt.

Ce qui manque

Les numéros de téléphone et la réputation vendeur. has_phone te dit qu'un numéro existe. Piloterr ne le renvoie jamais, à aucun palier, et il n'y a pas de profil vendeur derrière non plus. Si la donnée de contact est le but du job, cette API ne peut pas faire le job.

La reprise quand un run casse. Il s'arrête net sur erreur au lieu de se mettre en pause. lobstr.io met le run en pause et garde ce qu'il a déjà collecté, donc tu reprends ; ici, le batch se termine, et relancer depuis le début coûte des crédits une deuxième fois. Sur un job de 50 000 annonces, c'est la différence entre un retard et une réécriture.

La rétention des données. Piloterr ne stocke rien. La réponse HTTP est la seule copie, donc si ton écriture échoue avant que l'insertion soit validée, cet enregistrement est perdu et tu paies à nouveau pour le récupérer. lobstr.io conserve les résultats 28 jours.

Les bibliothèques clientes. Pas de SDK, pas de CLI. Tu écris toi-même le client HTTP, la boucle de pagination, les retries et la limitation de débit. Prévois une journée de plomberie que lobstr.io livre en pip install.
Des erreurs sans ambiguïté. 401 couvre à la fois « clé API invalide » et « limite de débit dépassée », donc une boucle de retry ne peut pas distinguer un throttling d'un identifiant mort sans parser le corps. Pousser la concurrence augmente le taux de 500 plutôt que le débit, donc les deux signaux d'échec les plus fréquents sont tous les deux trompeurs.

Coût

Coût
Plan Prix / mois Crédits Limite de débit Pour 1k résultats
Premium 49 $ 18 000 7 req/s 2,72 $
Premium+ 99 $ 40 000 10 req/s 2,48 $
Startup 249 $ 110 000 15 req/s 2,26 $
Startup+ 499 $ 230 000 20 req/s 2,17 $
Enterprise 799 $ 390 000 25 req/s 2,05 $
Enterprise+ 999 $ 530 000 30 req/s 1,88 $
Une annonce coûte environ 2 crédits, un appel /ad plus à peu près un appel /search amorti.
  1. Annonces : 5,44 $ les 1 000 à l'entrée, 3,76 $ les 1 000 au plancher publié
  2. Recherche seule, en abandonnant l'appel /ad : 2,72 $ les 1 000 à l'entrée, 1,88 $ au plancher

La facturation ne porte que sur les requêtes réussies, et l'essai est de 500 crédits sans carte bancaire.

Avantages et inconvénients

Avantages Inconvénients
Vraiment synchrone, un GET et tu as les données Aucun numéro de téléphone, à aucun prix
Le worker unique le plus rapide, 20 annonces/min Aucune couche de réputation vendeur
Le prix d'entrée le moins cher, 5,44 $/1k S'arrête net sur erreur au lieu de se mettre en pause
Essai gratuit, 500 crédits, sans CB Aucune rétention des données
Les données géo les plus riches et toutes les tailles d'image Pas de SDK, pas de CLI
Description complète et nombre de favoris 401 mélange échec d'auth et throttling
Serveur MCP d'exécution
Facture uniquement les requêtes réussies

Comment l'utiliser

Requête

curl -G 'https://api.piloterr.com/v2/leboncoin/search' \ -H 'x-api-key: YOUR_API_KEY' \ --data-urlencode 'query=https://www.leboncoin.fr/recherche?category=9&locations=Paris'
f
Ça renvoie ads[] avec pagination.total_pages, donc tu sais quand t'arrêter.

Requête

curl -G 'https://api.piloterr.com/v2/leboncoin/ad' \ -H 'x-api-key: YOUR_API_KEY' \ --data-urlencode 'query=3227906670'
f

L'endpoint d'annonce accepte soit un simple ID d'annonce, soit une URL complète. Les deux marchent.

Un attribut dans la réponse ressemble à ça, et les libellés français sont le vrai avantage.

Réponse

{ "key": "type_real_estate_sale", "value": "ancien", "value_label": "Ancien", "key_label": "Type de vente", "generic": true }
f
La documentation complète des endpoints est sur docs.piloterr.com.

Est-il légal de scraper Leboncoin ?

Avertissement : je ne suis pas juriste, et rien de tout ceci n'est un conseil juridique. Si tu montes une opération sérieuse, parles-en à quelqu'un qui connaît le droit français et européen.

Est-ce que Leboncoin l'autorise ? Non.

En fait, le site prend activement des mesures pour l'empêcher... le robots.txt interdit l'accès automatisé, les conditions interdisent d'extraire son contenu, et la protection anti-bot bloque les scripts à vue.

Est-il légal de scraper Leboncoin ?

Mais est-ce que ça le rend illégal ? Pas forcément, tant que tu restes dans le RGPD et le droit français et que tu ne bombardes pas le site.

Est-il légal de scraper Leboncoin ?
  1. Scraper des données non substantielles pour un usage interne est globalement admis
  2. Republier ou distribuer commercialement les données de Leboncoin est hors limites... un scraper a été condamné à 50 000 € dans l'affaire Entreparticuliers c. Leboncoin (2021), et le droit français des bases de données (article L342-3 du Code de la propriété intellectuelle) va dans ce sens
  3. Les données personnelles des vendeurs comme les numéros et les e-mails relèvent du RGPD, donc il te faut une base légale pour les collecter
Pour tous les détails et la jurisprudence derrière tout ça, va voir l'article de lobstr.io sur la légalité du scraping de Leboncoin et la série juridique plus large.

FAQ

Leboncoin a-t-il une API officielle ?

Oui, mais pas pour les annonces. Leboncoin publie l'API Argus® sur api.leboncoin.auto, avec OAuth 2.0 et une documentation complète. Elle fait du référentiel véhicule, de la cote Argus et de l'identification par plaque. Aucun endroit ne renvoie une petite annonce. Pour les données d'annonces, il n'existe aucune API officielle.

Puis-je utiliser l'API auto de Leboncoin pour récupérer les annonces de voitures ?

Non. Elle identifie et cote des véhicules : recherche par plaque, données de carte grise, cote Argus, valeur résiduelle. Elle ne renvoie jamais une annonce, un prix demandé ou un vendeur. Elle n'est pas non plus en self-service, et même un compte de test exige un contrat annuel.

Quelle est la différence entre l'API officielle et une API de scraping ?

Elles répondent à des questions différentes. L'API Argus® cote des véhicules à la plaque, et ne lit jamais la marketplace. Les API de scraping extraient les données publiques des annonces, gèrent la couche anti-bot pour toi, et facturent au résultat réussi.

Pourquoi les scrapers Leboncoin se font-ils bloquer ?

Leboncoin fait tourner une des protections anti-bot les plus strictes de toutes les marketplaces européennes, et elle est activement maintenue. Un simple script ou un navigateur headless par défaut tombe sur un mur de vérification presque immédiatement, et avoir les outils de développement ouverts fait partie des déclencheurs listés par Leboncoin lui-même. Passer au travers implique une dépense continue en proxies résidentiels et une maintenance permanente face à des changements que tu ne contrôles pas.

Existe-t-il une API Leboncoin synchrone ?

Oui, Piloterr. Un seul GET renvoie les données dans la même réponse. lobstr.io est asynchrone : tu crées un Squid, tu le lances, tu interroges, tu récupères. Si un utilisateur attend la réponse, c'est du sync qu'il te faut.

Peut-on récupérer les numéros de téléphone des vendeurs via une API Leboncoin ?

Oui, avec une seule. Le Listings & Phone Search Export de lobstr.io renvoie le vrai numéro dans le même run que l'annonce, à 6 crédits par numéro et facturé uniquement quand un numéro est trouvé. Il faut un compte Leboncoin synchronisé. Piloterr ne renvoie qu'un booléen has_phone et jamais le numéro. Sur mon jeu de test de 59 annonces, 27 vendeurs avaient un numéro exposé.

Combien coûte le scraping de Leboncoin à grande échelle ?

Les données d'annonces reviennent à 2 $ les 1 000 sur lobstr.io à grande échelle, ou 3,76 $ les 1 000 sur Piloterr à son plancher publié. Les numéros de téléphone sont exclusifs à lobstr.io, à 5 $ les 1 000, et tu ne paies les crédits téléphone que sur les annonces où un numéro est réellement trouvé. À l'entrée, l'ordre s'inverse, avec Piloterr qui démarre à 5,44 $ contre 8 $ pour lobstr.io.

Comment récupérer les données dans un tableur ou un workflow ?

lobstr.io te les livre. Les résultats s'exportent en CSV, Excel ou JSON, et peuvent être poussés directement vers Google Sheets, S3, SFTP, e-mail ou un webhook sans écrire de boucle de récupération. Piloterr renvoie du JSON dans la réponse HTTP, et tout ce qui vient après, tu le construis.

Combien de temps mes données sont-elles conservées ?

28 jours sur lobstr.io. Zéro sur Piloterr. Piloterr ne stocke rien, donc la réponse est ta seule copie... persiste-la dès réception.

Conclusion

Leboncoin a une API officielle, et elle cotera ta voiture à merveille. Pour tout ce qui touche à la marketplace elle-même, il te faut un tiers.

  1. lobstr.io si tu veux de la profondeur et de la durabilité. Six endpoints, la seule source de numéros de téléphone vendeur et de données de réputation, des fiches entreprise B2B avec SIREN et SIRET, une fiabilité publiée, et 2 $ les 1 000 à grande échelle. Tu paies ça en asynchrone, en lenteur par worker, et en absence de palier gratuit
  2. Piloterr si tu veux une réponse dans une seule requête. Rapide, peu chère au démarrage, vraiment synchrone, avec les meilleures données géo et image des deux. Tu abandonnes les numéros, la réputation vendeur, et toute rétention de données

Si tu construis un pipeline de monitoring, note que le Status Checker coûte 1 crédit et ne renvoie aucune donnée personnelle. Surveille pour pas cher, enrichis de façon sélective.

Envie de leads Leboncoin avec numéro vérifié, sans passer ton temps à surveiller des logins ? Lance l'export téléphone et fais tourner ton premier Squid.

Tu cherches la version no-code de cette comparaison ? J'ai testé tous les scrapers Leboncoin dédiés dans Meilleurs scrapers Leboncoin en 2026.
Tu as testé un outil que j'ai loupé, ou obtenu d'autres chiffres ? Écris-moi sur LinkedIn... je le reteste et je mets à jour avec plaisir.

Related Articles

Related Squids