---
title: "Extract"
method: POST
path: "/api/v1/extract"
tags: ["Extract"]
---

# Extract

`POST /api/v1/extract`

## Request

- Base URL: `https://lenz.io`
- URL: `https://lenz.io/api/v1/extract`
- Auth: HTTP bearer

Extract verifiable claims from arbitrary text.

Runs the extraction step on its own — no research, no debate, no credit
charge. Enumerates every distinct major factual
claim in the input (up to 100), ordered most-check-worthy-first, in
`claims` (one item for a single claim, `[]` for none). Claims returned
here verify cleanly when submitted verbatim to `POST /verify`.

Pass `focus` to narrow the result to the claims you care about — a short
description such as `"market size, growth and competitors"`, at most 300
characters. A focus selects from the claims the extractor found and
nothing else: it cannot add a claim, reword one, reorder them, change the
language, or change what counts as a claim. Ordering stays
most-check-worthy-first.

`status` is one of:

- `ready` — claims were found (and, with a `focus`, at least one matched).
- `no_checkable_claim` — no claim in the input could be checked against
  public evidence.
- `no_match` — claims were found but none fall within your `focus`. The
  unfocused list is never substituted; widen the focus and call again.

`text` can also be a single public web page URL (http or https, nothing
else in the field). Lenz reads the page, or a YouTube video's transcript,
and extracts the claims from its first 50,000 characters. Pages behind a
login (Facebook, Instagram, Threads, LinkedIn) can't be read. A URL call
typically takes 5-40 seconds, so give it a 90-second client timeout (SDK
2.13 and later do). A page that cannot be read answers 502
`extraction_failed`; when the services that read pages are down, 503
`upstream_unavailable` with `Retry-After`. Neither uses a unit of the
daily cap.

Pass `locate: true` to keep only the claims that can be traced directly
back to your text, and get each claim's `positions`: the passages that
make it, with `start` / `end` offsets into `text` as you
sent it, in Unicode code points. A claim the text does not make, or makes
with a different figure, is left out, so the list says what the author
wrote and nothing else. Offsets count code points, not UTF-16 units: in
JavaScript slice with `Array.from(text).slice(start, end).join('')`.
For a URL the offsets are `null` and each position carries its passage.
Locating adds a few seconds, never more than 20. If it cannot run,
every `positions` is `null` and the claims are returned unfiltered. `locate`
defaults to `false`.

Accepts up to 50,000 characters (longer input is truncated). Free for
API-key holders, capped at 1000 calls per ACCOUNT per day (resets at
00:00 UTC) regardless of input length — a focused call costs the same one
unit as an unfocused one. The cap is shared across all of the account's
keys.

**Versions.** 200: `2026-10-11` receives `ExtractOut`, `2026-05-13` receives `ExtractOutLegacy`; 422: `2026-10-11` receives `ValidationErrorOut`, `2026-05-13` receives `ValidationErrorOutLegacy`; default: `2026-10-11` receives `ErrorOut`, `2026-05-13` receives `ErrorOutLegacy`.

## Headers

- `X-Lenz-API-Version` string

## Request body

- ExtractIn
  - `text` string, required: The document to extract claims from. Up to 50,000 characters; longer input is truncated. Or a single public web page URL (http or https, nothing else in the field): Lenz reads the page, or a YouTube video's transcript, and extracts the claims from its first 50,000 characters.
  - `language` string: ISO 639-1 code for the language of the emitted claims. Omitted: English. `auto`: detected from the submitted text (the same rule as lenz.io: a supported language, or English when the text is short, English or in a language we do not answer in). A code always wins. Responses carry the code that was used, never `auto`. For a `text` that is one URL, `auto` reads the page.
  - `focus` string: Optional. Narrows the result to the claims this describes, e.g. "market size, growth and competitors". At most 300 characters — a longer focus is rejected, never truncated. A focus can only select from the claims the extractor found: it cannot add a claim, reword one, reorder them, or change what counts as a claim. When nothing matches, `status` is `no_match` and `claims` is empty; the unfocused list is never substituted.
  - `locate` boolean, nullable: Optional, default `false`. When `true`, only claims that could be traced directly back to your text are returned, and each claim's `positions` say where in the text it is made. A claim found nowhere in the text, or found with a different figure, is left out; so is a list that ends up empty, which answers `no_checkable_claim`. Adds a few seconds, never more than 20. If the claims cannot be located, every `positions` is `null` and the list is returned unfiltered.

## Response `200`

OK

- ExtractOut: The claims found in the submitted text. `claims` lists every claim found, most check-worthy first: one item for a single claim, `[]` when there is none. `status` is `ready` when claims were found, `no_checkable_claim` when no claim in the text could be checked against public evidence, and `no_match` when a `focus` was given and no claim falls within it. With `locate: true`, only claims traced back to the text are listed, and each claim's `positions` give the passages that make it.
  - `status` 'ready' | 'no_checkable_claim' | 'no_match'
  - `claims` ExtractedClaimOut[]
    - `claim` string, required
    - `positions` PositionOut[], nullable: Only with `locate: true`: every place the text makes this claim, in text order, at most 10. `null` when `locate` was not set or the claims could not be located.
      - `start` integer, nullable, required: Where the passage starts in `text` as you sent it, in Unicode code points (not UTF-16 units or bytes). Half-open with `end`. `null` when `text` was a URL: the page is not returned, so there is nothing to index, and `text` carries the passage instead.
      - `end` integer, nullable, required: Where the passage ends, exclusive; `null` as for `start`.
      - `text` string, nullable, required: The passage itself, as it appears in the text. `null` on a citation position, whose row already carries the statement.
  - `domain` string
  - `key_entities` ExtractedEntityOut[]
    - `name` string
    - `type` string
  - `presumed_intent` string
  - `original_input` string
  - `language` string, nullable: The language the claims are written in, as an ISO 639-1 code: the one you sent, `en` when you sent none, or the detected one when you asked for detection. Pass it on to `/assess` or `/verify` to keep a chain in one language. Absent on a replay of a response stored before this field existed.

## Other responses

- `422`: A field to fix
- `default`: An error

---

[API](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api.md) · [All operations](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lenz/apis/lenz-ai-fact-checking-api/revisions/6150947324bf?raw)
