{"id":51079056,"url":"https://github.com/maxgfr/leboncoin-cdp","last_synced_at":"2026-06-23T16:33:07.162Z","repository":{"id":337065486,"uuid":"473364133","full_name":"maxgfr/leboncoin-cdp","owner":"maxgfr","description":"Undetectable Leboncoin scraper using a real browser via Chrome DevTools Protocol and Next.js data routes. No Puppeteer, no automation flags, zero bot detection.","archived":false,"fork":false,"pushed_at":"2026-06-16T10:04:05.000Z","size":14738,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-16T11:24:39.151Z","etag":null,"topics":["anti-bot","bot-detection","browser-automation","browser-fingerprinting","cdp","chrome-devtools-protocol","leboncoin","scraping","stealth","stealth-scraping","web-scraping"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxgfr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-03-23T21:29:28.000Z","updated_at":"2026-06-16T10:06:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/maxgfr/leboncoin-cdp","commit_stats":null,"previous_names":["maxgfr/leboncoin-cdp-scraper","maxgfr/leboncoin-cdp"],"tags_count":4,"template":false,"template_full_name":"maxgfr/typescript-swc-starter","purl":"pkg:github/maxgfr/leboncoin-cdp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fleboncoin-cdp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fleboncoin-cdp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fleboncoin-cdp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fleboncoin-cdp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxgfr","download_url":"https://codeload.github.com/maxgfr/leboncoin-cdp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fleboncoin-cdp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34698696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-bot","bot-detection","browser-automation","browser-fingerprinting","cdp","chrome-devtools-protocol","leboncoin","scraping","stealth","stealth-scraping","web-scraping"],"created_at":"2026-06-23T16:33:06.998Z","updated_at":"2026-06-23T16:33:07.146Z","avatar_url":"https://github.com/maxgfr.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# leboncoin-cdp\n\nManage your Leboncoin listings from **local markdown + photos**, then **publish and\ndelete** them on your own account via the **Chrome DevTools Protocol** — built on the\noriginal zero-bot-detection CDP scraper. Shipped as a [skills.sh](https://skills.sh) agent\nskill (a thick `SKILL.md` playbook + a single zero-dependency CLI bundle).\n\n```bash\nnpx skills add maxgfr/leboncoin-cdp\n```\n\nMarkdown is the source of truth. You (or your agent) write and enrich the description —\ngrounded by comparable live listings — then the skill drives the « déposer une annonce »\nform on your real, logged-in browser to publish. **Semi-automatic and safe by default:** it\nfills the form and uploads the photos, but you review on screen and click\n« Déposer mon annonce » yourself.\n\n## Why CDP (and why it isn't detected)\n\nInstead of Puppeteer (flagged by DataDome), everything runs through a **raw WebSocket CDP**\nclient attached to your *real* browser profile: real first navigation sets the cookies, and\nall interaction runs as in-page JavaScript (`Runtime.evaluate`) — indistinguishable from the\nsite's own frontend. The skill launches a **separate** browser instance against a one-time\ncopy of your profile (`~/.lbc-scraper`) and **never touches your running browser**.\n\n## The skill workflow\n\n```bash\nnode scripts/leboncoin.mjs new macbook-air-m1 --title \"MacBook Air M1\" --category \"Informatique\"\n# → drop photos into annonces/macbook-air-m1/photos/, write the description in annonce.md\n\nnode scripts/leboncoin.mjs comparables macbook-air-m1      # scrape similar ads → comparables.md\n# → set price / category / attributes from the comparables\n\nnode scripts/leboncoin.mjs validate macbook-air-m1         # structural gate (exit≠0 if invalid)\nnode scripts/leboncoin.mjs publish  macbook-air-m1         # fills the form + uploads photos, you click publish\nnode scripts/leboncoin.mjs list                            # see local annonces + their state\nnode scripts/leboncoin.mjs delete  macbook-air-m1          # remove a published ad\n```\n\n| Command | What it does |\n|---|---|\n| `new \u003cslug\u003e` | Scaffold `annonces/\u003cslug\u003e/annonce.md` + `photos/` (a draft). |\n| `comparables \u003cslug\u003e` | Scrape similar live listings → `comparables.json` + `comparables.md` (grounding). |\n| `validate \u003cslug\u003e` | Required fields, ≥1 photo, real description, `status: draft`. |\n| `publish \u003cslug\u003e` | Fill the deposit form + upload photos via CDP. Semi-auto; `--yes` auto-submits; `--dry-run` fills only. |\n| `delete \u003cslug\u003e` | Remove a published ad (confirms unless `--yes`). |\n| `list` / `status` | Show local annonces and their published state. |\n| `scrape` | The original read-only scraper (search results + ad details). |\n\nSee `SKILL.md` and `references/` for the full playbook, the markdown schema, the deposit-form\nselector map, and the safety/captcha notes.\n\n### Markdown schema (source of truth)\n\n```markdown\n---\ntitle: \"MacBook Air M1 2020 — 256 Go\"\ncategory: \"Informatique\"\nprice: 650\nzipcode: \"75012\"\nattributes:\n  brand: \"Apple\"\n  model: \"MacBook Air M1\"\nphotos: []          # empty = every image in photos/, sorted\nstatus: draft\n---\nThe description body you write / enrich.\n```\n\n`publish` writes back `leboncoin_id`, `leboncoin_url`, `published_at` and flips\n`status: published`. Full contract: `references/markdown-schema.md`.\n\n## The scraper (read-only)\n\nThe original scraper lives on as the `scrape` subcommand — raw CDP + Next.js data routes,\nzero detection, all categories, macOS + Linux, Brave/Chrome/Opera/Chromium.\n\n```bash\nnode scripts/leboncoin.mjs scrape --query \"category=2\u0026locations=Lyon\u0026price=0-10000\" --with-details\nnode scripts/leboncoin.mjs scrape --query \"https://www.leboncoin.fr/recherche?category=9\" -o paris\n```\n\nFlags: `--query/-q`, `--output/-o`, `--config/-c`, `--with-details/-d`, `--details-only`,\n`--max-pages`, `--rate-limit`, `--retries`, `--output-dir`, `--save-raw`, `--browser/-b`,\n`--chrome-path`, `--port/-p`, `--timeout`, `--reset-profile`. Output JSON goes to\n`--output-dir` (default `./assets`). Env vars: `CHROME_PATH`, `PAGE_TIMEOUT`, `MAX_RETRIES`,\n`RATE_LIMIT`, `MAX_PAGES`, `OUTPUT_DIR`, `SAVE_RAW`, `LBC_SCRAPER_HOME`.\n\n\u003e **Breaking change (3.0):** the old `pnpm start -- --query …` is now\n\u003e `node scripts/leboncoin.mjs scrape --query …`.\n\n## Safety\n\n- **Semi-auto by default** — the engine never clicks the final publish for you unless you\n  pass `--yes` (which is still not headless: a captcha at submit needs a human).\n- **DataDome** challenges are detected and wait up to 5 min for you to solve them.\n- **Your account, your terms** — automating posts/deletes may violate Leboncoin's ToS and\n  risks account action. See `references/captcha-and-safety.md`.\n\n## Development\n\nZero **runtime** dependencies: the TypeScript in `src/` is bundled by tsup into a single\ncommitted ESM file, `scripts/leboncoin.mjs` (`ws` is inlined), runnable on Node ≥ 18 with no\ninstall.\n\n```bash\npnpm install\npnpm run build       # tsup → scripts/leboncoin.mjs\npnpm test            # vitest\npnpm run typecheck\npnpm run check:build # rebuild and assert the committed bundle is reproducible\npnpm run demo        # offline smoke: validate the example annonce\n```\n\nReleases are automated with **semantic-release** on push to `main` (Conventional Commits):\nit syncs the version across `package.json` / `src/types.ts` / `SKILL.md`, rebuilds the\nbundle, and publishes a GitHub release with the tarball. No npm-registry publish.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fleboncoin-cdp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxgfr%2Fleboncoin-cdp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fleboncoin-cdp/lists"}