Ricardo.ch Scraper
Unofficial, independently developed project — not affiliated with, endorsed by, or sponsored by Ricardo AG. "Ricardo" is a trademark of its respective owner.
Fetches every listing matching a search query from ricardo.ch — Switzerland's largest general marketplace — for free, no API key. Ricardo sells everything (laptops, phones, furniture, ...), so this scraper is built around free-text search, not a fixed taxonomy; "laptop" is used as the running example below, but nothing about the code is category-specific.
ricardo.ch sits behind a Cloudflare bot challenge with no separate public API (unlike AutoScout24), so this scraper drives a real, fingerprint-patched Firefox via camoufox to pass the challenge like a normal browser, then parses each listing's page for its full record. See docs/REFERENCE.md for exactly how, and for the two Cloudflare-specific fixes baked in.
This project is modeled directly on autoscout24-scraper — same repo shape, ScrapeResult/CSV/JSON contract, and library-and-CLI dual usage — so code written against one transfers to the other with minimal changes.
🤖 Robot-friendly. This project is explicitly intended to be run, read, imported, or adapted by AI agents and bots, same as a human developer — see License.
Setup
Requires pipenv.
git clone https://github.com/danyk20/ricardo-scraper.git
cd ricardo-scraper
pipenv install --dev
scrape() installs its own pinned, verified Firefox build on first run via ensure_pinned_browser() — never run camoufox fetch yourself (it would install a known-broken "latest" build); see docs/REFERENCE.md for why.
Contributing, linting, and testing commands: see CONTRIBUTING.md.
Usage
CLI
pipenv run python ricardo_scraper.py "laptop"
Prints progress, then writes laptop.csv and laptop.json in the current directory. Installed via pip install instead? Drop pipenv run — the same command is ricardo-scraper "laptop".
| Flag | Description |
|---|---|
--version |
Print the installed version and exit |
query |
Free-text search term, e.g. "laptop" or "iphone 13" (required, positional) |
--locale |
Ricardo locale (de/fr/it), default de |
--category |
Ricardo category id or name, e.g. 39272 or notebooks — requires detail mode (default on). All valid ids: docs/CATEGORIES.md |
--out |
Output file base name, without extension. Defaults to a slugified version of the query |
--no-detail |
Skip visiting each listing's own page; keep only summary fields |
--price-from / --price-to |
Filter by price in CHF, client-side (inclusive, either end optional) |
--max-results |
Cap on how many listings to collect |
--delay |
Seconds between requests (default 1.5) — raise this if you get rate-limited |
--show-browser |
Show the browser window instead of running fully headless (default: no window) |
-v / --verbose |
Also show debug-level detail |
-q / --quiet |
Suppress progress output; only warnings/errors (mutually exclusive with -v) |
Price and category filters are applied client-side, not by Ricardo's own search — see docs/REFERENCE.md for why that's the one place this project's interface deviates from AutoScout24's.
# Only laptops under CHF 500
pipenv run python ricardo_scraper.py "laptop" --price-to 500
# Fast mode: search summary only, skip visiting each listing
pipenv run python ricardo_scraper.py "laptop" --no-detail
# French-language site
pipenv run python ricardo_scraper.py "ordinateur portable" --locale fr
As a library
pip install ricardo-scraper
from ricardo_scraper import scrape
result = scrape("laptop", price_to=500)
for row in result.rows: # list[dict], CSV-ready
print(row["title"], row.get("price"), row["url"])
result.to_csv("laptops.csv") # optional — no files are written unless you ask
Every ricardo.ch category ships with the package, too — the IDs category= accepts, each with its parent so you can rebuild the hierarchy:
from ricardo_scraper import CATEGORIES
notebooks = next(c for c in CATEGORIES if c["id"] == 39272)
# {"id": 39272, "name": "Notebooks", "slug": "notebooks-39272", "parent_id": 39091,
# "depth": 1, "path": "Computer & Netzwerk > Notebooks"}
children = [c for c in CATEGORIES if c["parent_id"] == 39091] # everything under Computer & Netzwerk
Full scrape() signature, the ScrapeResult return type, browser-session reuse, and the complete JSON/CSV field schema: docs/REFERENCE.md.
Testing
pipenv run pytest # unit tests (fast, no network, no browser)
pipenv run pytest -m e2e --no-cov # end-to-end tests against the real live site
Unit tests mock the browser layer entirely (via FakeBrowserSession) and cover 100% of ricardo_scraper.py. E2E tests drive a real camoufox browser against ricardo.ch — expect occasional unrelated failures from Cloudflare; rerun after a cooldown. Detail: docs/REFERENCE.md.
Contributing
See CONTRIBUTING.md for dev setup and pre-PR checks.
Be a reasonable citizen: the default delay between requests, and reusing one browser session for a whole scrape run, are both intentional — this renders real pages through a real browser, not a lightweight API call. Don't crank up concurrency.
License
Released under the MIT License — you can use, copy, modify, merge, publish, distribute, and sell copies of this code, for free, for any purpose, commercial or not, as long as the license text stays attached. No warranty.
AI agents, LLM-based coding assistants, and other bots are explicitly welcome to use this project — to run the scraper, read and parse its output, import scrape() into another project, or read and adapt its source — under exactly the same terms as a human, with no additional restriction and no need to ask permission. That's why docs/REFERENCE.md documents the full function signature, return type, and data schema: so a bot can integrate correctly without a human in the loop.
This license does not grant any rights to Ricardo's own data or terms of service — this project only automates requests to publicly viewable pages any visitor's browser can already load; what you do with the results is between you and them.
Metadata
Release files for ricardo-scraper 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ricardo_scraper-0.2.3.tar.gz | 219.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ricardo_scraper-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 285.1 kB
Release files / ricardo_scraper-0.2.3.tar.gz
| Download URL | ricardo_scraper-0.2.3.tar.gz |
|---|---|
| Size | 219.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49e6a6a0d2b88c331ff9f39223faaffbeec2575aedfad050027e2f3d858e7565
|
|
BLAKE2b-256 checksum How to use checksums |
0e8a34ad7554c1e84b95bee12cbb64919ce3e729ded931a64bb0a9b73621996c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / ricardo_scraper-0.2.3-py3-none-any.whl
| Download URL | ricardo_scraper-0.2.3-py3-none-any.whl |
|---|---|
| Size | 65.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c7c6f3aca3fddd2fa04342955ac66a3f0ff0cd2de213acd02f9ba16376137993
|
|
BLAKE2b-256 checksum How to use checksums |
a25be348847de08cf64819a4d04b104c269c24b218226ac76c4435072f7b3ccd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log