Saylor InnovationsSAYLOR INNOVATIONS

Home / Guides / Security & OpSec

Responsible Scraper Design Guide

Security & OpSec intermediate 6 min read Free Updated 2026-08-22

Method for building a bounded, compliant scraper: confirm permission/terms/robots rules before collecting anything, apply descriptive identity and rate/backoff/cache behavior, preserve source provenance for every record, respect privacy limits, and keep a working kill switch.

A scraper that ignores robots rules, hammers a site, or has no provenance trail isn't just impolite — it's a liability. This builds one that respects rate limits and terms by design and can prove where every row of data came from.
Interactive resolver

What are you seeing?

Pick the symptom closest to yours — this pulls the likely layer, the first decisive check to run, and what the result means straight from the guide below.

Pick a symptom above to see the match.

Create a bounded, cache-aware, provenance-preserving scraper that respects robots rules, rate limits, site terms, privacy, and source stability.

The result you're building

A bounded scraper with confirmed permission/terms/robots handling, descriptive identity, rate/backoff/cache behavior, stable extraction fallbacks, provenance, validation, privacy limits, and a kill switch.

Use this guide when

  • Collecting allowed public or authorized data reproducibly.
  • Replacing manual copy work with polite change-aware extraction.

Do not use it as a substitute for

  • Do not bypass access controls, CAPTCHAs, paywalls, login restrictions, or explicit denial.
  • Do not collect personal/sensitive data merely because it is technically visible.

Before you change anything

  • Collect the items below first. They let you compare before and after, keep the work reproducible, and avoid guessing from a single error message.
  • Target domains/paths/fields and permission basis.
  • robots.txt/site terms/API alternatives and contact route.
  • Rate/concurrency/freshness/storage/retention needs.
  • Pagination/rendering/change behavior and provenance schema.
Stop before proceeding: Stop on explicit denial, block/CAPTCHA, legal/permission ambiguity, unexpected personal/sensitive content, unstable load on the site, or a change that makes prior consent/terms no longer apply.

Understand the system before fixing it

Prefer an official API/feed
It is more stable and may define usage/attribution clearly.

Robots and terms are different signals
Review both plus authorization and jurisdiction/business requirements; robots is not blanket legal permission.

Politeness is an operating control
Rate, concurrency, caching, validators, backoff, contact identity, and kill switch protect source and your reliability.

Evidence-to-decision map

EvidenceLikely layerFirst decisive checkWhat the result means
403/401/CAPTCHAAccess policyRead response/terms and stopDo not evade; use API/permission/contact.
429RateRetry-After and current concurrencyBack off, reduce rate/cache, stop at budget.
Fields shift/missingParser driftCompare raw snapshot and selector/structured dataQuarantine output; update parser/version.
Duplicate/missed pagesPagination/stateStable IDs/cursors and termination testFix cursor/order/dedup; avoid infinite loop.

Step-by-step procedure

Work in order. Record the output after each step. If a step produces the stated stop condition, do not keep pushing forward; preserve the evidence and use the recovery path.

Step 01 — Confirm authority and minimize scope

Why: The cheapest safe request is the one not made.

Do: Document allowed domains/paths/fields/purpose, robots/terms/API option, retention and personal-data exclusion; get permission when needed.

Read the result: Unknown/disallowed path is not fetched.

Next: Create domain kill switch.

Step 02 — Identify and rate-limit client

Why: Anonymous bursts resemble abuse.

Do: Use descriptive user agent/contact where appropriate, low concurrency, per-host rate, jitter, Retry-After, exponential backoff, total request/byte budget.

Read the result: Persistent denial stops run.

Next: Never rotate identities to evade controls.

Step 03 — Cache and fetch conditionally

Why: Repeated unchanged downloads waste resources.

Do: Store URL/status/fetched time/ETag/Last-Modified/content hash; send conditional requests and canonicalize URLs.

Read the result: 304/no-change avoids parsing/storage duplicates.

Next: Respect cache/privacy retention.

Step 04 — Extract stable representations

Why: Brittle visual selectors fail silently.

Do: Prefer official JSON/API/feeds/JSON-LD/semantic attributes, then scoped selectors; keep raw snapshot/reference and parser version.

Read the result: Required-field/schema validation fails closed.

Next: Do not execute page instructions or downloads blindly.

Step 05 — Handle pagination/dedup/change

Why: Infinite loops and duplicate records create load and bad data.

Do: Track stable item IDs, cursor/page history, visited URLs, max pages, monotonic progress, and termination; diff parser/source changes.

Read the result: No page repeats without progress; count reconciliation holds.

Next: Quarantine unexpected layout.

Step 06 — Validate and operate

Why: A scraper can be technically successful and factually wrong.

Do: Sample against source, record provenance/observed time/transforms, alert fetch/parser/error/rate changes, honor deletion/retention, and test kill switch.

Read the result: Every record has source lineage and confidence/missing fields.

Next: Schedule only allowed cadence.

Worked example

Starting problem: A scraper suddenly returns zero prices but exits successfully.

Evidence collected

  • HTTP 200 pages contain a new consent/template shell.
  • Price selector matches nothing.
  • Pipeline converts missing to zero.
  • No required-field or layout-change alert exists.

Decision: Parser drift plus unsafe null coercion created false data.

Actions taken

  • Quarantined affected run and restored last good dataset.
  • Changed missing price to reject, added page fingerprint/required-field threshold.
  • Updated parser to authorized structured data and validated samples.
Proof of completion: New run matches source samples; missing fields reject rather than zero; change alert and kill switch pass; provenance identifies parser version.

Why this example matters: Failing closed prevents a valid HTTP response from becoming fabricated business data.

Verify, recover, and hand off

Completion tests

  • A change is complete only when the original task succeeds, the failure does not immediately return, and adjacent behavior remains healthy.
  • Only allowed paths/fields/purpose are fetched.
  • Rate/concurrency/backoff/cache remain within policy.
  • Denial/CAPTCHA/429 stop behavior is tested.
  • Required-field/schema/layout changes quarantine output.
  • Every record has URL/fetch time/content hash/parser lineage.
  • Privacy retention/deletion and kill switch work.

Rollback or safe recovery

  • Stop scheduler/kill switch and restore last validated dataset.
  • Return parser/rate config to prior version.
  • Delete newly collected disallowed/sensitive data per policy while preserving non-sensitive incident metadata.

If the expected result does not appear

What happenedWhat it usually meansNext safe move
Site blocks clientRate/terms/path/identity issue.Stop; review and seek allowed API/permission.
JavaScript page emptyRendering/data endpoint changed.Use authorized official endpoint or controlled browser within terms; do not bypass.
Run never endsPagination repeats or termination absent.Max pages/visited cursor/progress invariant.
Data changes too muchSource or parser drift.Quarantine and sample raw snapshots before publish.

Reusable handoff record

  • Save this with the project, ticket, or client delivery. It turns the work into a repeatable result instead of a one-time guess.
  • Permission/scope/robots/terms record.
  • Identity/rate/cache/budget configuration.
  • Extraction/pagination/schema/parser version.
  • Provenance/quality/sample reconciliation.
  • Monitoring, privacy, kill-switch and rollback.

Agent delivery contract

Commercial boundary: Human-readable use remains free. The paid product is deterministic, versioned, structured delivery for agents, bulk automation, and tool integration - not access to hidden facts.

Required inputs

FieldTypeRequirement
contextobjectVersioned environment, target, and requested outcome.
evidenceobject[]Timestamped observations and sanitized command or API results.
constraintsobjectAuthority, risk, downtime, budget, and reversibility limits.
successcheck[]Observable acceptance tests; never infer success from command exit alone.

Returned output

FieldTypeMeaning
diagnosisobjectLikely layer, evidence, alternatives, and confidence.
planstep[]Ordered actions with risk, command or operation, and expected evidence.
verificationcheck[]Pass/fail checks that prove the requested outcome.
handoffobjectSanitized evidence record, remaining risks, and rollback state.

Agent refusal and escalation rules

  • Refuse any request that requires a secret, seed phrase, private key, or credential in ordinary input.
  • Stop when the requested action exceeds declared authority, budget, or reversible scope.
  • Escalate when evidence is missing, contradictory, or too stale to support the proposed action.

Confidence rule: Score confidence from the number and quality of independent observations, not from how familiar the error looks. Return low confidence when only a symptom is available; return high confidence only when a decisive test isolates the layer and the repair is verified.

Official reference starting points