Skip to main content

Free, keyless Python scraper & library for autolina.ch vehicle listings — any make/model, price/mileage/year filters, CLI + library API, MIT licensed.

Project description

Autolina Scraper

CI PyPI License: MIT Python 3.11+

Unofficial, independently developed project — not affiliated with, endorsed by, or sponsored by autolina.ch ag. "autolina" is a trademark of its respective owner.

Fetches every listing for a given make/model from autolina.ch — for free, no API key, no paid scraping service. It's designed as a drop-in, API-compatible sibling to autoscout24-scraper: same scrape() signature, same ScrapeResult shape, same CLI flags — swap the import and point it at a different Swiss car marketplace.

autolina.ch has no public JSON API the way AutoScout24 does — it's a single server-rendered Angular app — so this scraper parses the same server-rendered HTML, using a small set of generic, resilient selectors rather than brittle hardcoded field positions (see "How the data is obtained"). By default it does a two-phase scrape: search to collect every matching listing id, then visit each one individually for the full record (VIN, energy data, standard/optional equipment, dealer contact info, images, ...). Every spec row and equipment item the site renders is kept — nested objects are flattened into parent_child CSV columns, lists are joined into semicolon-separated cells — nothing is silently dropped. Results are always ordered newest-first.

🤖 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. It only ever requests autolina.ch's open, robots.txt-permitted routes and identifies itself honestly; see Compliance for exactly which routes and why.

Setup

Requires pipenv (brew install pipenv).

git clone https://github.com/danyk20/autolina-scraper.git
cd autolina-scraper
pipenv install --dev

Contributing, linting, and testing commands: see CONTRIBUTING.md.

Usage

CLI

pipenv run python -m autolina_scraper.cli --make VW --model Tiguan

Prints progress, then writes vw_tiguan.csv and vw_tiguan.json in the current directory. Installed via pip install instead? The same command is autolina-scraper --make VW --model Tiguan.

Flag Description
--version Print the installed version and exit
--make Make name or slug, e.g. VW or vw (required)
--model Model name or slug, e.g. Tiguan or tiguan (required)
--domain Country domain (default ch) — autolina.ch only exists for ch
--category Vehicle category — only car is supported (no motorcycles)
--out Output file base name, without extension. Defaults to <make>_<model>
--no-detail Skip per-listing detail visits; keep only summary fields (faster, fewer fields)
--delay Seconds between requests (default 1.0) — raise this if you get rate-limited
--price-from / --price-to Filter by price in CHF (inclusive, either end optional)
--mileage-from / --mileage-to Filter by mileage in km (inclusive, either end optional)
--year-from / --year-to Filter by first-registration year (inclusive, either end optional)
--max-results Cap the number of listings collected/detail-visited (default: unlimited)
-v / --verbose Also show debug-level detail (mutually exclusive with -q)
-q / --quiet Suppress progress output; only warnings/errors (mutually exclusive with -v)

Filters combine with AND and are applied server-side (confirmed against the live site), so they also cut down how many listings get visited in the detail phase. A mistyped make/model prints a clean error (plus, for an unknown model, the list of valid models) instead of crashing.

# Fast mode: search results only, skip per-listing detail
pipenv run autolina-scraper --make VW --model Tiguan --no-detail

# 2018 or newer, under CHF 30'000, under 60'000 km
pipenv run autolina-scraper --make VW --model Tiguan --price-to 30000 --year-from 2018 --mileage-to 60000

# A broad, unfiltered search can run into the hundreds of listings — each an
# extra request in the detail phase. Cap it:
pipenv run autolina-scraper --make VW --model Tiguan --max-results 50

As a library

pip install autolina-scraper
from autolina_scraper import scrape

result = scrape("VW", "Tiguan", price_to=30000, year_from=2018)

for row in result.rows:          # list[dict], CSV-ready
    print(row["price"], row["mileage"], row["url"])

result.to_csv("vw_tiguan.csv")   # optional — no files are written unless you ask

A plain, unfiltered search can easily run into the hundreds of listings — max_results caps how many get a (comparatively expensive) detail-page visit, without affecting total_elements (the site's true full count):

result = scrape("VW", "Tiguan", max_results=50)

Need more control over which listings are worth a detail visit — cheapest first, only what changed since your last run, whatever suits your use case? Use the search and detail phases separately instead of the single scrape() call, mirroring the AutoScout24 reference's own search_listings()/visit_all_listings() split:

from autolina_scraper import search_listings, visit_all_listings
from autolina_scraper.http import new_session

session = new_session()
total, listings = search_listings(session, "vw", "tiguan", max_results=200)

listings.sort(key=lambda listing: listing["price"] or 0)
cheapest_ten = listings[:10]

enriched = visit_all_listings(session, cheapest_ten)  # only 10 detail requests

Full scrape() signature, the ScrapeResult return type, the complete field schema, and how this differs from the AutoScout24 reference: docs/REFERENCE.md.

Testing

pipenv run pytest                    # unit tests (fast, no network), coverage gate enforced
pipenv run pytest -m e2e --no-cov    # end-to-end tests against the real live site

Unit tests mock all HTTP (via responses) against real saved HTML fixtures — no network access, no live-site dependency. E2E tests target a small-inventory make/model to confirm the scraper still works against the live site.

Contributing

See CONTRIBUTING.md for dev setup, pre-PR checks, and what to do if autolina.ch changes its markup and a test starts failing.

Be a reasonable citizen: the default request delay is intentional — this project only works because it sticks to autolina.ch's own open, robots.txt-permitted routes. Don't remove the delay, don't crank up concurrency, and never point this at the site's Cloudflare-protected internal routes.

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 autolina.ch's own data or terms of service — this project only automates requests to routes autolina.ch's own robots.txt permits a normally-identified crawler to fetch; what you do with the results is between you and them.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autolina_scraper-0.3.1.tar.gz (264.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autolina_scraper-0.3.1-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file autolina_scraper-0.3.1.tar.gz.

File metadata

  • Download URL: autolina_scraper-0.3.1.tar.gz
  • Upload date:
  • Size: 264.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for autolina_scraper-0.3.1.tar.gz
Algorithm Hash digest
SHA256 98dc43cc442764aa5c0070563c5580f7c9b6b842fccd35701e3b0490fa2368c0
MD5 f0f8bced8b8311791989eb12e3c68d74
BLAKE2b-256 e39ba5ac89b2a4bd89c2e9e49eab66a687ba19d58bed6e129561d4c8d97daf83

See more details on using hashes here.

Provenance

The following attestation bundles were made for autolina_scraper-0.3.1.tar.gz:

Publisher: release.yml on danyk20/autolina-scraper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file autolina_scraper-0.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for autolina_scraper-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e9d7913269ede0bc4a483b005090c6e547743d0b6c73524a714f960830254f4b
MD5 0539e15c13e6ec54ec1d2acb0d2b152c
BLAKE2b-256 26547716a4e9ddc14818f263156eac58bde5a49ac7d37cea71a131d2922286e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for autolina_scraper-0.3.1-py3-none-any.whl:

Publisher: release.yml on danyk20/autolina-scraper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page