CLI tool · Claude Skill · Zero dependencies
Read and analyze any kleinanzeigen.de listing from your terminal or from Claude — cars, electronics, real estate, furniture. Dealer detection, hidden damage flags, duplicate listings, image download.
pip install kleinanzeigen-reader # installs the kl-read CLI
pip install "kleinanzeigen-reader[mcp]" # + the MCP server for AI systemsFrom source:
git clone https://github.com/its-me-prash/kleinanzeigen-reader.git
cd kleinanzeigen-reader && pip install -e .Or run without installing:
python -m kl_reader "https://www.kleinanzeigen.de/s-anzeige/..."# Analyze a single listing
kl-read "https://www.kleinanzeigen.de/s-anzeige/bmw-e87-120d/12345-216-8032"
# Compare two listings
kl-read URL1 URL2
# JSON output
kl-read URL --json
# Download images
kl-read URL --images ./photos
# Save report
kl-read URL --output report.json╔══════════════════════════════════════════════════════════════╗
║ KLEINANZEIGEN READER ║
╠══════════════════════════════════════════════════════════════╣
║ Titel BMW E87 120d 163ps ║
║ Kategorie fahrzeuge ║
║ Verkäufer ✅ Privat ║
║ Preis 1.400 € ║
║ Standort 79395 Neuenburg am Rhein ║
╠══════════════════════════════════════════════════════════════╣
║ Kilometerstand 380.001 km ║
║ TÜV/HU bis ⚠️ fehlt ║
║ Leistung 163 PS ║
║ Kraftstoff diesel ║
║ Getriebe manuell ║
║ Schaden ⚠️ JA ║
║ Emissionsklasse euro4 ║
╠══════════════════════════════════════════════════════════════╣
║ Bewertung ★☆☆☆☆ ║
╚══════════════════════════════════════════════════════════════╝
⚠️ FLAGS
🔴 SCHADEN deklariert (schaden:t)
🟡 Sehr hoher Kilometerstand: 380.001 km
🟡 TÜV-Datum = EZ-Datum — wahrscheinlich abgelaufen
🔴 Motor: N47D20A — Steuerketten-Rückruf — prüfen lassen
Kleinanzeigen embeds all structured data in three places that never go away regardless of frontend redesigns:
1. Schema.org JSON-LD — Google SEO requirement, always present. Title, price, main image.
2. ad_attributes GTM string — every listing's attributes packed as pipe-separated values sent to Google Tag Manager:
km:380001|aussenfarbe:blau|schaden:t|power:163|tuevdate:2026-04|shift:manuell
The schaden:t damage flag lives here — invisible in the mobile UI without looking at raw HTML.
3. li field — "li":"0" = private seller, "li":"1" = commercial dealer. Confirmed by the badge text in HTML.
| Feature | Details |
|---|---|
| Dealer detection | li field + badge text + undeclared dealer heuristic |
| Damage flag | schaden:t from hidden GTM string |
| Motor ID | BMW N47/M47, known chain/belt issues |
| Duplicate detection | Same car listed twice at different prices |
| Image download | Direct from CDN — up to 1600×1096 ($_57) |
| Hidden fields | Exact GPS, member-since, price type, native price reduction, status |
| Signals | View counter, seller portfolio, reserved/sold status, PriceTracker |
| Authenticated mode | Bring your own session → 👀 views + ⭐ watchers for any ad, full ad JSON, your own paused ads |
| Categories | Cars, electronics, real estate, furniture, general |
| Output formats | Terminal box UI, JSON, file report |
New in v1.2 — usable from any AI system: MCP server, function-calling schemas, AGENTS.md
and a CLI (see Use with any AI system above), plus PyPI packaging
(pip install kleinanzeigen-reader) and AI-discovery metadata (llms.txt).
v1.1 — reverse-engineering of the official Android app (references/mobile-api.md): larger
images ($_57 = 1600×1096), hidden fields (exact lat/long, userSince, priceType, native
originalPrice), demand signals (view_counter), seller portfolios, reserved/sold detection, a
local PriceTracker, and an optional authenticated mode (Session, bring-your-own-token) for
per-ad view/watch counts and your own paused listings. Optional curl_cffi (Chrome-TLS) transport
is auto-used when installed; the stdlib fallback keeps the core zero-dependency.
from kl_reader import fetch, extract, get_flags, get_rating
result = fetch("https://www.kleinanzeigen.de/s-anzeige/.../12345-216-8032")
data = extract(result["html"])
flags = get_flags(data)
rating = get_rating(data, flags)
print(data["damage"]) # True/False
print(data["seller_type"]) # "private" / "commercial"
print(data["km"]) # "380001"cp -r claude-skill/ ~/.claude/skills/kleinanzeigen-reader/Then in Claude: just paste any kleinanzeigen.de URL.
The reader is not Claude-only — every major AI system can drive it:
| AI system | How |
|---|---|
| Claude (Desktop / Code) | MCP server, or the skill in SKILL.md / claude-skill/ |
| ChatGPT (desktop) · Cursor · Cline · Windsurf · Zed | MCP server (below) |
| OpenAI / Gemini / Mistral / Groq / Ollama (function calling) | Tool schemas in tools/openai-tools.json |
| Copilot / Codex / Aider & other coding agents | AGENTS.md |
| Anything else | the CLI — kl-read "<url>" --json — machine-readable output |
MCP server (Model Context Protocol — the cross-vendor standard):
pip install "kleinanzeigen-reader[mcp]"
kleinanzeigen-mcp # stdio server{ "mcpServers": { "kleinanzeigen": { "command": "kleinanzeigen-mcp" } } }Tools exposed: read_listing, compare_listings, listing_views,
seller_other_listings, track_price. For AI-discovery metadata see llms.txt.
git clone https://github.com/its-me-prash/kleinanzeigen-reader.git
cd kleinanzeigen-reader
pip install -e .kl-read "https://www.kleinanzeigen.de/s-anzeige/..."
kl-read URL1 URL2 # Vergleich
kl-read URL --json # JSON-Ausgabe
kl-read URL --images ./fotos- Privat vs. Gewerblich — inkl. Erkennung undeklarierten Händler
schaden:t— Schaden deklariert, oft in der mobilen Ansicht unsichtbar- Abgelaufener oder fehlender TÜV
- BMW Motor-Identifikation (M47N2 vs. N47 — Steuerketten-Rückruf)
- Duplikat-Erkennung: selbes Fahrzeug zweimal zu verschiedenen Preisen inseriert
- Bilder direkt vom CDN
cp -r claude-skill/ ~/.claude/skills/kleinanzeigen-reader/git clone https://github.com/its-me-prash/kleinanzeigen-reader.git
cd kleinanzeigen-reader
pip install -e .kl-read "https://www.kleinanzeigen.de/s-anzeige/..."
kl-read URL1 URL2 # comparaison
kl-read URL --json
kl-read URL --images ./photos- Vendeur particulier ou professionnel — avec détection des marchands non déclarés
schaden:t— dommages déclarés, souvent invisible sur mobile- Contrôle technique expiré ou manquant
- Identification du moteur BMW (N47 vs M47 — problème de chaîne de distribution)
- Doublon : même véhicule listé deux fois à des prix différents
- Images téléchargées directement depuis le CDN
cp -r claude-skill/ ~/.claude/skills/kleinanzeigen-reader/kleinanzeigen-reader/
├── kl_reader/
│ ├── __init__.py public API
│ ├── __main__.py python -m kl_reader entry
│ ├── cli.py terminal UI
│ ├── scraper.py HTTP fetch with mobile UA
│ ├── extractor.py JSON-LD + GTM + DFP parsing
│ ├── analyzer.py flags, motor ID, star rating
│ ├── comparator.py multi-listing comparison
│ ├── images.py CDN image downloader
│ ├── signals.py view counter, portfolio, status, PriceTracker
│ └── auth.py authenticated mode (bring your own session)
├── references/
│ ├── mobile-api.md app CAPI map, auth scheme, hidden fields (RE)
│ └── ad-attributes-fields.md
├── claude-skill/
│ ├── SKILL.md Claude skill instructions
│ └── kl_reader/ bundled package (copy of above)
├── mcp_server.py MCP server for any MCP-capable AI system
├── tools/
│ └── openai-tools.json function-calling schemas (OpenAI/Gemini/Mistral/…)
├── tests/ 27 unit tests (extractor · signals · auth)
├── pyproject.toml packaging (PyPI: pip install kleinanzeigen-reader)
├── requirements.txt (empty — core is zero-dep; MCP is an optional extra)
├── AGENTS.md vendor-neutral agent instructions
├── llms.txt AI/LLM discovery metadata
├── CLAUDE.md auto-loaded by Claude Code
└── LICENSE
Is there a Kleinanzeigen API? There is no public one. This tool reads the same
structured data the site embeds in every listing (JSON-LD, GTM ad_attributes, DFP block)
and documents the app's private mobile API in references/mobile-api.md.
Can AI assistants use it? Yes — via the MCP server (Claude, ChatGPT desktop, Cursor, Cline, Windsurf, Zed), function-calling schemas (OpenAI, Gemini, Mistral, Ollama), or the CLI.
Does it detect if a seller is a dealer? Yes — from the li/lsc fields plus badge text
and an undeclared-dealer heuristic. Dealers owe a 2-year statutory warranty (§ 475 BGB).
Can it see how many views a listing has, or track price over time? Yes — listing_views
returns the view counter, and track_price / PriceTracker build a price history over time.
Does it need an account or API key? No. Core features are anonymous. An optional authenticated mode (bring your own session token) unlocks per-ad view/watch counts and your own listings — it never touches other users' private data.
- fb-marketplace-analyzer — same approach for Facebook Marketplace
- vag-connect-ha — VAG vehicle Home Assistant integration
MIT