You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: clamp wait_timeout, UTF-8 HTML, and gate CI on Ruff plus Hadolint (#35)
* fix: clamp wait_timeout and return scrape envelope on schema 422
Gem clients send wait=28 against a 20s service cap; clamp inbound wait so scrape still runs, and keep remaining schema 422s in the scrape envelope the gem already parses.
* fix: utf-8 html headers and request-tier 403 escalate
Botasaurus HTML must be labeled UTF-8 so clients do not treat octet-stream as abort; 401/403/429 on the request tier already escalate to browser, and tests now lock that El País/NOS path.
* test: lock utf-8 identity and clamp wait on POST /scrape
Already-correct Caffè/CJK HTML must survive normalize; README timeout and content-type now match the 20s UTF-8 runtime.
* chore(lint): add Ruff with Makefile and CI
Host-side lint/format as the fast gate so Docker smoke is not the only quality check.
* style: apply Ruff autofix so check and format pass
Bring the existing modules in line with the new linter so CI lint is green on this branch.
-`wait_timeout_seconds` outside `[1, SCRAPE_TIMEOUT_SECONDS]` (default 20) is clamped into that range so `/scrape` still runs; remaining schema 422 bodies use the scrape envelope (`url`, `error`, `error_category`, `request_id`), not FastAPI `detail`.
Copy file name to clipboardExpand all lines: README.md
+10-13Lines changed: 10 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ Docker-only FastAPI service that uses [Botasaurus](https://github.com/omkarcloud
8
8
-`GET /health`
9
9
-`POST /scrape`
10
10
- Intended usage: run and test through Docker only.
11
-
- Runtime boundary: async FastAPI handler delegates sync browser work to a bounded threadpool (`SCRAPE_MAX_WORKERS`, default `4`), with a per-request timeout (`SCRAPE_TIMEOUT_SECONDS`, default `25`).
11
+
- Runtime boundary: async FastAPI handler delegates sync browser work to a bounded threadpool (`SCRAPE_MAX_WORKERS`, default `4`), with a per-request timeout (`SCRAPE_TIMEOUT_SECONDS`, default `20`).
12
12
- On-demand isolation-first runtime: every scrape request runs with an ephemeral browser profile and request-scoped runtime dir, then gets fully cleaned up.
13
13
14
14
## Prerequisites
@@ -139,22 +139,19 @@ Request options (contract):
139
139
-`organic_get`: only `organic_get`
140
140
-`max_retries`: `0..3`, default `2` (attempts = `1 + max_retries`, with `auto` capped by 3 strategy steps).
141
141
-`wait_for_selector`: if set, response waits for selector before capture (routes to browser tier).
142
-
-`wait_timeout_seconds`: selector wait timeout (default `15`, capped by service timeout).
142
+
-`wait_timeout_seconds`: selector wait timeout (default `15`). Values outside `[1, SCRAPE_TIMEOUT_SECONDS]` (default `20`) are clamped into that range so scrape still runs.
143
143
-`scroll` / `scroll_to_bottom`: if true, scrolls the page to trigger lazy-loaded feeds (routes to browser tier).
144
144
-`block_images`: pass image blocking to driver. Default `true`.
145
+
-`block_images_and_css`: pass image+css blocking to driver. Default `false`.
145
146
-`block_trackers`: block tracking/ad networks and web fonts to speed up rendering. Default `true`.
147
+
-`wait_for_complete_page_load`: pass page-load wait behavior to driver. Default `true`.
148
+
-`user_agent`: explicit user agent string passed to driver.
146
149
-`headers`: custom HTTP request headers forwarded to request client or browser session.
147
150
-`cookies`: key-value cookies map forwarded to request client or browser session.
148
-
149
-
Currently accepted passthrough options (implemented, not part of stable request-options contract):
150
-
151
-
-`block_images_and_css`: pass image+css blocking to driver.
152
-
-`wait_for_complete_page_load`: pass page-load wait behavior to driver.
153
-
-`user_agent`: explicit user agent string passed to driver.
154
151
-`window_size`: two-item integer list `[width, height]` passed to driver.
155
152
-`lang`: browser language passed to driver (for example `en-US`).
156
153
-`headless`: pass headless browser mode to driver. Default `false`.
157
-
-`proxy`: proxy URL passed to driver.
154
+
-`proxy`: proxy URL passed to driver. Invalid or blocked proxy URLs are rejected by SSRF guardrails.
-`headers`, `status_code`, `final_url`: best-effort metadata and may be `null`.
184
+
-`html`: rendered page HTML, UTF-8-normalized.
185
+
-`headers`, `status_code`, `final_url`: best-effort metadata and may be `null`. When `html` is present, document `headers``content-type` is `text/html; charset=utf-8`.
189
186
-`error`: populated when scrape fails or challenge is detected on final attempt.
190
187
-`metadata_error`: populated when metadata extraction fails but HTML scrape succeeds.
191
188
-`request_id`: unique per request for tracing.
@@ -207,7 +204,7 @@ Status codes:
207
204
-`200`: scrape completed without `error`.
208
205
-`400`: URL rejected by validation (for example unresolved host).
209
206
-`403`: URL blocked by SSRF guardrails.
210
-
-`422`: request schema validation failed.
207
+
-`422`: request schema validation failed. Body is the scrape error envelope (`url`, `error`, `error_category`, `request_id`), not FastAPI `{"detail":[...]}`.
0 commit comments