A ceramic water mill turning a mixed stream of paper sheets, photo prints, and ledger pages into a single clear channel of plain text slips
All posts

Fetch turns the messy web into text your code can use

Invoices arrive as scanned PDFs, prices live in rendered pages, and evidence sits in spreadsheets. AIVAX Fetch extracts readable text — and optionally typed JSON — from URLs and files through one endpoint, metered in processing units instead of model tokens.

Production input rarely arrives as clean text. A supplier sends a scanned invoice as a PDF. The price you need sits in a JavaScript-rendered product page. The evidence your monitor must compare lives in a spreadsheet attached to a ticket, or in a screenshot pasted into chat. Before any model can summarize, classify, or decide, something has to read those sources and turn them into text the rest of the pipeline can handle.

That reading step is infrastructure, not a prompt. A chat model can describe an image when asked, but per-image generation calls are the wrong tool for bulk conversion: they cost model tokens per item, return prose shaped by the prompt rather than the source, and mix reading with reasoning in a single call that is hard to budget or audit. Fetch separates the two. It extracts the text first, reports what the extraction cost, and leaves the reasoning to a later step that receives only the passages your code selected.

One endpoint for pages, documents, and images

Fetch and OCR reads web pages and supported documents into text. The endpoint is POST /api/v1/web/fetch: it accepts a non-empty contents array of URLs or base64 data URIs, up to 10 MB per item, and returns per-item index, extractedText, processingUnits, and error fields. The index is the zero-based position of the input, so a batch can associate every result with its source without relying on completion order. With returnErrors: true, a failed item keeps an explicit error entry instead of silently disappearing from the batch.

The supported inputs cover the formats messy pipelines actually encounter:

What Fetch reads from each source type
SourceFormatsWhat you get
Web pagesHTML, XHTMLReadable content with markup and non-content elements removed; JavaScript and CSS rendered before extraction
Plain textTXT, MarkdownThe document text, keeping existing Markdown formatting
PDFsPDFText from digital documents plus OCR text from scanned pages; mixed PDFs combine both
Images with textPNG, JPEG, WebP, TIFF, BMPRecognized text from screenshots, receipts, and scanned documents with legible writing
Office documentsDOC, DOCX, ODT, RTF, PPT, PPTX, ODPDocument text in a readable textual representation
SpreadsheetsXLSX, ODS, CSVCell content as text; formulas and macros are not executed

Two boundaries matter. Audio and video are not Fetch inputs: for speech, use audio transcription; for interpreting visual content beyond its text, use Media Descriptions, which generates model-guided descriptions instead of extracting existing text. And extraction is not reproduction: OCR and layout handling can lose structure or characters in tables, charts, and scans, so consequential names, numbers, and quotations still deserve verification against the original source.

From extracted text to typed JSON in the same call

Text is enough when the next step is indexing, comparison, or passing passages to a model. When the next step is a branch in code, the pipeline needs fields, not paragraphs. Fetch accepts an optional responseSchema: a JSON Schema applied to each item's extracted text, with the structured result returned in extractedObject alongside the original extractedText. An instructions field inside the schema steers the conversion the way a system instruction would.

A receipt pipeline shows the difference. Without a schema, the caller receives the receipt's text and parses it with its own code. With a schema naming merchant, total, and date, the same call returns both the text for the audit trail and an object the ledger writer can consume directly:

const response = await fetch(
  "https://inference.aivax.net/api/v1/web/fetch",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.AIVAX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      contents: [receiptImageUrl],
      returnErrors: true,
      responseSchema: {
        type: "object",
        instructions: "Extract the receipt fields exactly as printed.",
        properties: {
          merchant: { type: "string" },
          total: { type: "number" },
          date: { type: "string" },
        },
        required: ["merchant", "total", "date"],
      },
    }),
  },
);

const item = (await response.json()).data.results[0];

if (item.error) {
  throw new Error(`Extraction failed: ${item.error}`);
}

await ledgerWriter.write(item.extractedObject);
await auditLog.attach(item.extractedText);

The schema conversion runs as a separate inference step per item, billed under its own usage category, while the text extraction keeps its own processingUnits accounting. Both figures arrive in the same response item (processingUnits and jsonProcessingUnits), so the caller sees the reading cost and the structuring cost independently instead of one blended token bill.

Priced in processing units, not model tokens

Fetch and OCR extraction is metered in processing units (PUs), not input and output tokens. Plain text and Markdown cost zero PUs: there is nothing to render or recognize. Rendered HTML is charged at 10 PUs per second of rendering time. Document and image conversion accrues PUs per item through the OCR path, and daily included allowances plus per-thousand-PU overage rates depend on the account plan: 1,000 PUs per day included on Free with overage at $0.15 per 1,000 PUs, 10,000 per day on Pro at $0.05, and 50,000 per day on Max at $0.02. Current allowances and charges live on the AIVAX Pricing page; account quotas and rate limits are under Plans and limits.

The practical consequence is that reading scales differently from reasoning. A monitor that checks fifty product pages a day pays rendering seconds, not fifty chat completions. A backfill that extracts ten thousand receipts pays OCR units per image, with the per-item figure visible before any model sees the text. When only some items need structuring, only those items carry the schema-conversion cost. Budget the reading step from PU rates, budget the reasoning step from token rates, and neither estimate has to smuggle the other inside it.

Three ways in, depending on who controls the flow

The same extraction serves three callers. Backend workflows that own the control flow use the direct API above: they choose the URLs or data URIs, keep the per-item results, and decide what enters the next stage. MCP-compatible agents and automation clients use the Web Utilities MCP fetch_url tool, which accepts one to five public URLs per call and returns aggregated text. An AIVAX model that needs to read a URL mid-inference uses the OpenUrl built-in tool instead. The MCP tool takes public URLs only; inline base64 data goes through the direct API.

That division mirrors the one in Research is a pipeline: search discovers, fetch reads: search produces candidate URLs, fetch turns the selected ones into inspectable text, and the application keeps both steps so a reviewer can see which pages were discovered, which were read, and which passages support the downstream result. Use the direct API when the backend owns that flow; use the MCP or built-in tool when an agent or model should decide when to read.

The trust boundary from that post applies unchanged. Extracted text is external, untrusted source material, not instructions. A fetched page can contain prompt-like text, stale claims, or content unrelated to the query; fetching changes its availability, not its authority. Keep control data separate from retrieved content, and require any downstream model output to stay grounded in the URLs and passages the application selected.

Read first, reason second

Messy input is the normal case: rendered pages, scanned PDFs, screenshots, office documents, spreadsheets, and unstructured text that no sender will clean up for you. Fetch turns each of them into text — and, when the next step needs fields, into JSON shaped by your schema — through one endpoint with per-item errors and per-item cost. The model step that follows receives text worth reasoning about, at a reading price measured in processing units rather than tokens.