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
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98dc43cc442764aa5c0070563c5580f7c9b6b842fccd35701e3b0490fa2368c0
|
|
| MD5 |
f0f8bced8b8311791989eb12e3c68d74
|
|
| BLAKE2b-256 |
e39ba5ac89b2a4bd89c2e9e49eab66a687ba19d58bed6e129561d4c8d97daf83
|
Provenance
The following attestation bundles were made for autolina_scraper-0.3.1.tar.gz:
Publisher:
release.yml on danyk20/autolina-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
autolina_scraper-0.3.1.tar.gz -
Subject digest:
98dc43cc442764aa5c0070563c5580f7c9b6b842fccd35701e3b0490fa2368c0 - Sigstore transparency entry: 2213273291
- Sigstore integration time:
-
Permalink:
danyk20/autolina-scraper@54d29ebc655309396ba8058b820571309e28b619 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/danyk20
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@54d29ebc655309396ba8058b820571309e28b619 -
Trigger Event:
push
-
Statement type:
File details
Details for the file autolina_scraper-0.3.1-py3-none-any.whl.
File metadata
- Download URL: autolina_scraper-0.3.1-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9d7913269ede0bc4a483b005090c6e547743d0b6c73524a714f960830254f4b
|
|
| MD5 |
0539e15c13e6ec54ec1d2acb0d2b152c
|
|
| BLAKE2b-256 |
26547716a4e9ddc14818f263156eac58bde5a49ac7d37cea71a131d2922286e1
|
Provenance
The following attestation bundles were made for autolina_scraper-0.3.1-py3-none-any.whl:
Publisher:
release.yml on danyk20/autolina-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
autolina_scraper-0.3.1-py3-none-any.whl -
Subject digest:
e9d7913269ede0bc4a483b005090c6e547743d0b6c73524a714f960830254f4b - Sigstore transparency entry: 2213273325
- Sigstore integration time:
-
Permalink:
danyk20/autolina-scraper@54d29ebc655309396ba8058b820571309e28b619 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/danyk20
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@54d29ebc655309396ba8058b820571309e28b619 -
Trigger Event:
push
-
Statement type: