Reliable web scraping depends on more than a successful HTTP request. A scraper can keep returning status 200 while receiving a challenge page, an empty template, or data that no longer matches your parser. This monitoring runbook explains what to track, how to set practical alerts, how to investigate changes, and when to revisit your checks so failures are detected before they become trusted data.
Overview
Web scraper monitoring is the practice of measuring both the health of a scraping job and the quality of the data it produces. Basic job monitoring answers questions such as “Did the process run?” and “Did it exit successfully?” Useful monitoring goes further: it asks whether the response was the expected page, whether the number of records is plausible, and whether the output changed for a technical reason or a real-world reason.
A good runbook separates three kinds of failure:
- Transport failures: DNS errors, connection timeouts, TLS problems, rate limits, unexpected redirects, and server errors.
- Content failures: CAPTCHA or challenge pages, login screens, consent walls, empty templates, missing fields, or JavaScript-rendered content that was not loaded.
- Processing failures: parser exceptions, selector mismatches, malformed embedded data, duplicate records, storage errors, and jobs that finish without publishing output.
Monitor these layers independently. A single “job succeeded” metric can hide a serious extraction failure. For example, the request may complete normally while a CSS selector returns zero elements. Treat the scraper as a pipeline: fetch, validate, extract, normalize, deduplicate, and store. Each stage should produce signals that can be inspected and alerted on.
For context, review your HTTP client choice when diagnosing connection behavior. The comparison of Requests, HTTPX, and aiohttp for web scraping can help you identify whether timeouts, concurrency, or retry settings belong in the monitoring investigation.
What to track
Request and response health
Record the target, request time, duration, status code, final URL, response size, and content type for every request or sampled request. Status-code distributions are more useful than a single status metric. A shift from mostly 200 responses to frequent 403, 429, or 5xx responses may indicate blocking, rate limiting, or an upstream outage. A sudden increase in redirects may indicate a login requirement, regional routing change, or a new intermediate page.
Latency should be tracked using a distribution rather than only an average. Record a percentile such as the 95th percentile alongside the maximum and timeout count. A gradual latency increase can precede timeouts, while a sudden increase may indicate that a target has changed its delivery path. Response size is another practical signal. Alert when the median or typical size moves outside a known range, but allow for targets whose page length naturally changes.
Challenge and empty-page detection
Do not rely only on status codes to detect blocks. Search response bodies for stable, target-specific indicators such as a known challenge title, a verification form, a login heading, or a required application shell. Keep these checks narrow enough to avoid false positives, and review them when the target changes its layout.
Track the proportion of responses that contain the expected page marker. This could be a product-list container, an article heading, a JSON property, or another structural element that should be present in a valid response. Also track empty extraction results. A zero-record result may be legitimate for a particular query, so compare it with the expected range for that target and request type rather than treating every zero as an incident.
Extraction and data quality
At extraction time, measure records found, records discarded, fields missing, parser exceptions, and duplicate keys. Field completeness is often a stronger signal than record count. A scraper may continue finding 100 items while the price, date, identifier, or pagination cursor is missing from every item.
Use stable data-quality checks where possible:
- Require a non-empty identifier for each record.
- Measure the percentage of records containing required fields.
- Compare record counts with recent runs using a target-specific baseline.
- Track duplicate rates before and after normalization.
- Validate dates, URLs, numeric fields, and enumerated values.
- Confirm that the output file, table, or queue was actually written.
Store a small sample of raw responses or sanitized response metadata for failed runs. This makes it easier to distinguish a parser regression from a target-side change without retaining unnecessary personal or sensitive information. For storage formats and operational trade-offs, the guide to JSONL, CSV, and SQLite for scraped data provides useful background.
Logs and trace context
Every log event should include enough context to connect a symptom to a specific run. Useful fields include run_id, job_name, target, request_url or a normalized route, page_number or cursor, attempt, status_code, duration_ms, response_bytes, records_found, records_written, parser_version, code_version, and an error category. Avoid logging cookies, authorization headers, tokens, or full pages that may contain sensitive data.
Cadence and checkpoints
Monitoring should operate at several cadences. At runtime, emit structured logs and metrics for each request or extraction batch. After every job, run a completion check that confirms expected output exists and includes records or an explicitly valid empty result. On a daily or per-run basis, review error rates, latency, response sizes, and field completeness for important targets.
Use a monthly or quarterly review for slower changes. Compare the current parser with recent successful runs, inspect the top failure categories, remove obsolete alert rules, and verify that test fixtures still represent the live page. A recurring review is especially important for scrapers that depend on CSS selectors, XPath, embedded JSON, pagination links, or JavaScript-delivered data. The practical guides to CSS selectors and XPath, pagination patterns, and network APIs for JavaScript-rendered sites can help structure those checks.
Example alert thresholds should be treated as starting points, not universal rules:
- Page-level error or timeout rate exceeds the normal baseline for two consecutive runs.
- Challenge or login-page matches appear in a meaningful share of responses.
- Required-field completeness falls below the agreed data-quality target.
- Record count drops sharply compared with the recent baseline.
- Duplicate rate rises above the normal range.
- Latency or response size remains abnormal across multiple samples.
- A scheduled job misses its completion window or produces no output.
Prefer alerts that combine persistence and impact. One slow request may not need attention; several slow runs that also produce fewer records do. Route high-confidence failures to an immediate incident channel and lower-confidence anomalies to a review queue. Include the target, first-seen time, recent values, baseline, code version, and a direct link to logs in the alert.
How to interpret changes
Begin with scope. If several unrelated targets fail at the same time, investigate shared infrastructure, DNS, credentials, deployment changes, or a common HTTP client configuration. If only one target changes, compare its raw response, final URL, status distribution, and page markers with the last known-good run.
Next, classify the symptom. A 403 or challenge marker suggests access behavior or request handling needs review; do not simply increase retries. A 429 pattern points to request pacing, concurrency, or target-side limits. A 200 response with an empty parser result usually indicates a content or selector problem. A normal record count with missing fields suggests a partial markup change, embedded-data change, or normalization bug.
Check deployment history before editing selectors. A new parser version, dependency update, proxy configuration, browser change, or timeout setting can create an apparent target failure. Compare the failing run with a known-good fixture and test the parser independently from the network request. If the target is JavaScript-rendered, verify that the data is being requested or rendered as expected; a static HTML fetch may legitimately contain only a shell.
For text extraction pipelines, validate the intermediate document rather than inspecting only the final text. The comparison of Trafilatura, Readability, and jusText, along with the guide to cleaning scraped HTML, is useful when a layout change affects downstream content quality. If the scraper extracts metadata, also verify JSON-LD and embedded JSON separately from visible HTML using the structured-data extraction guide.
When investigating a suspected block or site change, respect the target’s terms, access controls, and operational limits. Monitoring should help you stop or adjust a job safely, not encourage uncontrolled retries. Preserve the failed response metadata, record the action taken, and document whether the incident was resolved by configuration, parser maintenance, or a change in the target.
When to revisit
Revisit this runbook after any incident that exposed a missing signal. If a scraper delivered empty data for several runs without an alert, add a content or completeness check. If alerts fired repeatedly without actionable failures, refine the baseline, persistence window, or target-specific threshold. The goal is not to eliminate every variation; it is to make important changes visible without creating alert fatigue.
Schedule a formal review monthly for high-value or frequently changing targets, and quarterly for stable jobs. Also review monitoring immediately after a deployment, parser rewrite, HTTP client change, authentication change, pagination change, or move from static HTML to a browser or API workflow. Recheck challenge markers, page fingerprints, required fields, response-size ranges, and expected record counts whenever the target’s interface changes.
Use this short checklist at the next review:
- List the normal status, latency, response-size, and record-count ranges for each important target.
- Confirm that every job validates content, not just transport success.
- Test one known-good fixture and one intentionally malformed response.
- Inspect the last incidents and add a missing metric, log field, or runbook step.
- Verify that alerts identify the target, run, code version, symptom, and suggested first action.
- Document when to pause retries, roll back a deployment, or escalate a target-side change.
A scraper is ready for dependable operation when failures are classified, observable, and recoverable. Start with a small set of high-value signals, establish baselines from successful runs, and expand checks as the pipeline becomes more important. Revisit those assumptions on a regular cadence so monitoring evolves with the scraper rather than waiting for the next silent failure.