StructuredWeb
How it works

Four steps, and one of them
is the whole product.

The first three are what any extraction tool does. The fourth — checking the result against your schema before charging you for it — is the reason this exists.

01The pipeline

From a URL to a checked object.

  1. 01

    You write the schema

    A plain JSON Schema object — the shape you want back. Test it free against a sample first if you like; the playground runs the exact validator that decides billing.

  2. 02

    We read the page

    The URL is rendered like a browser would render it, then reduced to clean text — navigation, cookie bars and ad slots stripped. JavaScript-built pages work; a login wall does not.

  3. 03

    The text is fitted to your schema

    A model reads that text with your schema in front of it and returns one object. Its standing instruction is to omit a field the page never states rather than guess it — a guess would pass validation and be wrong.

  4. 04

    The object is validated, then billed

    Field by field against your schema. Valid, and the URL settles 4 credits. Invalid under strict, and it refunds — you still get the partial object and the list of what was missing.

02The gate

Strict mode, drawn.

Two runs that did exactly the same work upstream. Only one of them is a result, so only one of them is charged.

page yields every required key{ "name": "Pro", "price": 20 }VALIDATEvalidsettled4 creditsRUN Apage never states a price{ "name": "Pro" } missing: priceVALIDATEthinrefunded0 creditsRUN B
When to turn strict off

Set strict: false when a partial answer is still worth money to you — surveying two hundred competitor pages where half will be missing a field anyway, say. Every URL that produced any data is then charged, and valid plus missing_fields still come back so you can sort the complete rows from the ragged ones yourself. Leave it on when you are feeding a pipeline that will break on a null.

03Batches

Reserved for all. Settled for some.

Send up to 25URLs in one call. The billable unit is still one URL: the run reserves for the whole list up front so it can never overdraw mid-flight, then returns everything it didn't earn.

charged on a billable resultreturned otherwisenever billed above the reserve
ONE RUN · 5 URLSreserved20 crstripe.com/pricing3 plans4 crlinear.app/pricing4 plans4 cracme.io/pricingno price on pagevercel.com/pricing3 plans4 croldsite.net/planspage unreachablecharged 3 of 58 cr returned12 cr
04The response

Everything you need to decide what to do next.

Each URL comes back with its object, its verdict, and — when the verdict is no — the exact fields that were missing. Nothing is hidden behind a status code.

RESPONSE · one URL of a run
{
  "url": "https://acme.io/pricing",
  "final_url": "https://acme.io/pricing",
  "title": "Pricing — Acme",
  "data": { "name": "Growth" },
  "valid": false,
  "missing_fields": ["price"],
  "errors": ["price: required property is missing"],
  "used_tokens": 4180,
  "billed": false,      // strict mode: not charged
  "error": null
}

Try it against a schema you already have.