Bulk Google Autocomplete (Suggest) scraper and API — run many seeds × languages × countries per run with optional A–Z expansion for long-tail keyword research. Export suggestions to JSON or CSV. Public Suggest endpoint, no auth, no key.
Fix (reliability): 30-day public success rate was ~85-94% (customer
runs only — our own QA runs never failed). Reproduced the root cause: a
single transient curl_cffi network error (connection reset, DNS
failure, TLS handshake, timeout, or a malformed/non-JSON body from a
blocked request) raised straight out of session.get()/response.json()
— it was never caught by the retry loop (which only inspected an
already-returned response.status_code) and was not a RuntimeError, so
it bypassed main.py's per-tuple guard and crashed the entire run via
asyncio.gather(..., return_exceptions=False). One bad seed/locale combo
out of potentially hundreds took down the whole bulk run.
src/client.py: _get_with_retry now wraps session.get() and
response.json() in try/except RequestException and retries with the
same exponential backoff as HTTP 429/503 — this is exactly what the
module's own docstring already promised ("network errors") but never
implemented.
src/main.py: _process_tuple now isolates the parse+push phase too
(previously unguarded) as a defense-in-depth backstop, so any per-tuple
failure is logged and skipped rather than propagating. Cancellation
(BaseException) still propagates normally.
No change to input schema, output row shape, or PPE pricing/charging —
verified by local apify run against tests/fixtures/input.qa.json
(still 10 rows, identical field set) and against an adversarial bulk
input (unicode/emoji seeds, empty seeds, multiple locales) — 78 rows
across 16 tuples, exit 0, no crash.
7 new regression tests (51 → 58) pinning: retry-on-network-error,
retry-on-malformed-JSON-body, exhausted-retries-still-raises-RuntimeError,
and _scrape surviving a fetch/parse failure on one tuple among many.
0.0.1 — 2026-05-16
Initial release.
Bulk Google autocomplete scraper. Seeds × languages × countries
fan-out per run, optional A–Z alphabet expansion.
client=chrome (default, up to 15 suggestions + relevance scores)
or client=firefox (up to 10 suggestions, lean payload).
PPE pricing: actor-start $0.05, result-row $0.001.
Pydantic v2 input + dataset row validation.
curl-cffi chrome131 impersonation; concurrency capped at 2;
exponential backoff with Retry-After honoured.