Scrape used-car listings from AutoScout24.de (Germany's largest car marketplace) — make, model, price, mileage, first registration, fuel, transmission, power, body type, colour, dealer details, and photos. Paste any AutoScout24 search URL or filter by make/model; export to JSON or CSV.
Preventive: force-RESIDENTIAL proxy guard in _resolve_proxy_url.
Previously, missing or non-residential apifyProxyGroups fell back to
direct / datacenter routing, which AutoScout24's DataDome layer always
blocks with 403. Now _ensure_residential() enforces the RESIDENTIAL
group before every create_proxy_configuration call, regardless of what
the customer passed in proxyConfiguration. If the proxy configuration
is unavailable (plan without residential access or SDK error), the Actor
raises RuntimeError immediately with a clear plan-upgrade message
instead of silently looping on 403s.
country_code from apifyProxyCountry is preserved through the guard.
models.pyActorInput.proxy_configuration default already specifies
RESIDENTIAL; confirmed correct and unchanged.
README: added "Residential proxy required" note to Limitations and a new
FAQ entry explaining the RESIDENTIAL group error.
Added tests/test_proxy_guard.py — 10 unit tests covering the guard:
force on empty groups, force on datacenter group, passthrough when already
RESIDENTIAL, country_code passthrough, RuntimeError on None config, and
RuntimeError on create_proxy_configuration exception.
0.2.0 — 2026-06-05
Fix cloud-health failure: AutoScout24's DataDome layer blocks datacenter
proxies on every Apify auto-QA run → all 5 profile-rotation retries fail →
Actor exited non-zero → flagged "Under maintenance" after 3 days.
Introduced FullyBlockedError — a typed signal raised by _get_text only
when all retries are exhausted with HTTP block codes (401/403/405/429).
main.py catches it and exits 0 with a clear status message directing the
user to switch to the RESIDENTIAL proxy group. Genuine code bugs (parse
errors, unexpected exceptions) still propagate and fail loud.
Zero-result page-1 (empty search match, not a block) is now also a clean
exit-0 with a log warning instead of a RuntimeError. Mirrors the
kick-chat-archive "offline channel = empty success" pattern (commit ddd36a6).