// Use case · Extraction

Turn any set of pages into typed JSON

For pipelines that need fields, not HTML: send a JSON Schema or one sentence, point at URLs or a whole site, and pay only for the pages actually fetched.

  • credit per uncached page

    1

  • pages per request, max

    100

  • credits for a cache hit

    0

POST /api/v1/extract 200 OK
{  "success": true,  "data": {    "data": {      "tiers": [        { "name": "Starter", "monthlyUsd": 0 },        { "name": "Growth", "monthlyUsd": 49 }      ]    },    "sources": [      { "status": "fetched", "billed": true },      { "status": "cached", "billed": false }    ]  },  "credits": 1}
"credits" in the response
Two sources, one fetched and one from cache: one credit. Source URLs are trimmed here for width. This call debited 1 credit.

// Why

Stop writing a parser per site

The problem

Scrapers return markup; your code needs fields

  • Hand-written selectors break when a page changes, and every new site is a new parser.
  • Getting the fields right takes several tries, and each try refetches and repays for the same pages.
  • A whole-site job can fan out to far more pages than you planned for.

What Wayfern does

Describe the result; get JSON back with a receipt

  • Send a JSON Schema, a plain-English prompt, or both. Fields the pages do not state come back null.
  • Cached source pages are not billed, so the second attempt at a schema over the same pages costs nothing.
  • maxPages (1 to 100, default 10) caps both the fetching and the bill.

// How it works

One request, from URLs to fields

Authenticate with a wf_ token that carries the web scope. The extraction runs synchronously and returns the data, the sources and the charge together.

  1. Step 1 of 4

    Name the pages

    One URL, a list, or a trailing /* that discovers a site's URLs through map first.

    "urls": ["https://example.com/docs/*"]

  2. Step 2 of 4

    Describe the result

    A JSON Schema fixes the shape; a sentence lets the model pick the keys. One of the two is required.

    "schema" or "prompt"

  3. Step 3 of 4

    Wayfern fetches and extracts

    Uncached pages load in a real browser. Pages captured within maxAge (one hour by default) are reused.

    "maxPages": 10

  4. Step 4 of 4

    Read the receipt

    Each source says fetched, cached or failed and whether it was billed. credits is the total.

    "credits": 1

// Code

The same request in curl, Node.js and Python

A schema and a prompt together: the prompt steers what to look for, the schema fixes the shape.

POST /api/v1/extract
curl -X POST https://api.wayfern.com/api/v1/extract \
  -H "Authorization: Bearer wf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": ["https://example.com/pricing", "https://example.com/docs/*"],
    "prompt": "every pricing tier with its monthly cost and included seats",
    "schema": {
      "type": "object",
      "properties": {
        "tiers": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "monthlyUsd": { "type": "number" },
              "seats": { "type": "integer" }
            },
            "required": ["name", "monthlyUsd"]
          }
        }
      },
      "required": ["tiers"]
    },
    "maxPages": 10
  }'

// Targets

One URL, a list, or a whole site

urls is an array. Its shape is what changes between extracting one page and extracting a site.

  • One URL

    Point at one page when you know where the data lives. One uncached fetch, 1 credit.

    "urls": ["https://example.com/pricing"]

  • A list of URLs

    The model merges across the pages and prefers the most specific source where they disagree. maxPages still decides how many are fetched: raise it above 10 for a longer list.

    "urls": ["…/pricing", "…/enterprise"]

  • A whole site

    A trailing /* hands the base URL to map, which discovers URLs across that host: sitemaps first, page links second. Discovery is billed as a map call.

    "urls": ["https://example.com/docs/*"]

// Describe the result

A schema you own, or a sentence

With a schema, the object conforms to it, so tiers[0].monthlyUsd is a number your types already know. With only a sentence, the values come back under one data object keyed as your instruction implies: useful for exploring a page before you commit to a shape.

Request bodies and the response
{
  "urls": ["https://example.com/pricing"],
  "schema": {
    "type": "object",
    "properties": {
      "tiers": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "monthlyUsd": { "type": "number" }
          },
          "required": ["name", "monthlyUsd"]
        }
      }
    },
    "required": ["tiers"]
  }
}

The sources array is the receipt

  • Cache hits are free

    A source served from cache comes back as status: "cached", billed: false.

  • Failures are free

    A source that fails to load is status: "failed", billed: false, with the reason attached.

  • You control freshness

    maxAge defaults to one hour of cache reuse; set it to 0 to force a live fetch and pay for it.

  • Same bytes, same key

    The cache is keyed by URL plus the options that change the captured page, so a hit needs the same proxy mode and country.

// What it costs

1 credit per uncached source page

Re-running an extraction over pages still in cache costs nothing, which is what makes iterating on a schema cheap. At this rate the Developer plan’s 1,520 monthly credits cover 1,520 uncached pages.

40 URLs, 12 already in cache

maxPages: 40. Cached and failed sources are not billed.

Credits for: 40 URLs, 12 already in cache
ItemCredits
28 uncached source pages28
12 pages served from cache0

Total

28credits

about $0.35
at $0.0125 / credit

About 54 runs a month on Developer ($19 for 1,520 credits).

A wildcard over a docs site

/docs/* with maxPages: 50. The map call behind the wildcard is debited separately.

Credits for: A wildcard over a docs site
ItemCredits
map: 80 URLs returned (2 per 10)16
50 uncached source pages50

Total

66credits

about $0.83
at $0.0125 / credit

About 23 runs a month on Developer ($19 for 1,520 credits).

The same balance pays for browser sessions, crawls, screenshots and search. See the full rate card.

// FAQ

Questions about extraction

Do I need a JSON Schema?

No. Send a schema, a prompt, or both; sending neither is a 400. With no schema, values come back under one data object keyed as your instruction implies. Send both and the prompt steers what to look for while the schema fixes the shape.

What if a page does not state a value?

That field comes back null. The extractor reports only what is on the page, rather than a guess.

Can a wildcard run up a large bill?

No. maxPages is a hard ceiling on source pages fetched; wildcard expansion, de-duplication and fetching all happen under it, so two overlapping paths never bill a page twice. Credits are reserved for the worst case before any fetch, then only pages actually fetched are charged. The map call behind a /* costs 2 credits per started block of 10 returned URLs and is not included in the extract response's credits.

Does a /docs/* wildcard stay inside /docs?

Not necessarily. Map discovers URLs across the host, so the result can include pages outside that path. Pass an explicit list of URLs when the exact scope matters.

Can I get JSON from one page without /extract?

Yes. Ask /scrape for the json format with jsonOptions.schema or jsonOptions.prompt; the object lands on data.json beside the markdown. That bills 1 credit for the page plus the +4 output add-on. A scrape cache hit is still billed; only extract prices cache hits at zero.

What happens when credits run out?

The request stops rather than overspending. Plan credits are spent first, then pack credits; at zero the platform hard-stops unless auto top-up is on.

// Next step

Extract your first page in one request

Point the extract endpoint at one URL, iterate on the schema over cached pages for free, and keep the page ceiling where you set it.