API Reference
Request parameters, response schema, and error handling for POST /contents.
Endpoint: POST https://api.lcr.net/contents
Auth: Send your API key as a Bearer token: Authorization: Bearer <api-key>. Get a key at app.lcr.net.
The Contents API turns any public URL into clean, structured, LLM-ready data in real time, at scale, powered by the Grass network.
Request parameters
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
urls | string or string[] | No | — | URL to fetch. Accepts a single URL or an array. Currently one URL per request — more than one returns 400 Bad Request. |
text | boolean or TextOptions | No | enabled | Text extraction options. text is returned by default; pass text: false to omit only the text field (html and markdown are still returned). |
livecrawlTimeout | integer | No | 10000 | Livecrawl timeout in milliseconds. Values are clamped to 1–90000. |
countryCode | string | No | us | Two-letter ISO 3166-1 alpha-2 country code used to route the crawl through a country-specific proxy. Lowercased and trimmed; uk maps to gb. See Geotargeting. |
maxAgeHours | number | No | omit | Controls content freshness. See Content freshness. Positive values: hours to accept from cache (e.g. 24). Special values: 0 (always livecrawl), -1 (cache only). |
Text options
| Parameter | Type | Default | Description |
|---|---|---|---|
maxCharacters | integer | 20000 | Character limit applied to text, html, and markdown. Must be a positive number; missing, 0, negative, or non-numeric values fall back to 20000. There is no fixed upper bound. |
verbosity | string | "compact" | "compact" (main content: <article> → <main> → <body> fallback) or "full" (whole <body>). Applies to text only. |
Output size & truncation
Every result field — html, markdown, and text — is truncated to maxCharacters, which defaults to 20,000. To return a whole large page (for example full HTML), raise the limit and, for text, ask for the full body:
{
"urls": ["https://example.com"],
"text": { "verbosity": "full", "maxCharacters": 200000 }
}html and markdown always cover the full page up to maxCharacters. Passing text: false omits only text.
Cached responses are capped at 20,000 characters
Content is stored in the cache truncated to 20,000 characters. A response served
from cache ("source": "cached" or "cached-fallback") returns at most 20,000
characters regardless of the maxCharacters you request. To reliably get
full-length HTML, force a livecrawl with "maxAgeHours": 0.
Response schema
{
"requestId": "e492118ccdedcba5088bfc4357a8a125",
"results": [
{
"title": "Page Title",
"url": "https://example.com/page",
"id": "7668765c-2b66-4c50-b1ff-8c4bed8500c3",
"publishedDate": "2024-01-15T00:00:00.000Z",
"author": "Author Name",
"image": "https://example.com/image.png",
"favicon": "https://example.com/favicon.ico",
"html": "Full page content as html...",
"text": "Full page content as text...",
"markdown": "Full page content as markdown..."
}
],
"statuses": [
{
"id": "7668765c-2b66-4c50-b1ff-8c4bed8500c3",
"status": "success",
"source": "livecrawled",
"httpStatusCode": 200,
"strategy": "fast",
"credits": 1
}
],
"searchTime": 1301
}Top-level fields
| Field | Type | Description |
|---|---|---|
requestId | string | Unique request identifier. |
results | array | Result objects with extracted content. Only present for URLs that were successfully fetched. |
statuses | array | Per-URL status information. Always check this for errors. One entry per requested URL. |
searchTime | number | Time taken to fulfill the request, in milliseconds. |
results[]
Only present for URLs that were successfully fetched.
| Field | Type | Description |
|---|---|---|
id | string | Unique ID for this result. Matches the corresponding statuses entry. |
url | string | The requested URL. |
title | string | Page title. |
author | string | Author extracted from meta tags, if available. |
publishedDate | string | Published date extracted from meta tags, if available. |
image | string | OG image URL, if available. |
favicon | string | Favicon URL. Falls back to /favicon.ico if not found in markup. |
text | string | Extracted page text. Omitted only when text: false; truncated to maxCharacters (20,000 by default). |
html | string | Raw crawled HTML, truncated to maxCharacters (20,000 by default). |
markdown | string | Markdown rendering of the page, truncated to maxCharacters (20,000 by default). |
statuses[]
One entry per requested URL, regardless of success or failure.
| Field | Type | Description |
|---|---|---|
id | string | Unique ID for this entry. Matches the corresponding results entry on success. |
status | string | "success" or "error". |
source | string | On success: how content was retrieved (see table below). On error: the original request URL. |
httpStatusCode | number | HTTP status code from the upstream site, or a synthetic code on error. |
strategy | string or null | Fetch strategy used for the request: "fast", "browser", "tls", or "local-browser". null if no strategy was selected. |
credits | number | Credits charged for the fetch strategy: 1 for fast or tls, 2 for browser, 3 for local-browser, 1 when unresolved, and 0 for errors. |
error | object | Only present on error. See Error handling. |
statuses[].source values
Only meaningful on success entries.
| Value | Meaning |
|---|---|
"livecrawled" | Content was fetched live from the URL during this request. |
"cached" | Content was served from cache within the requested maxAgeHours window. |
"cached-fallback" | Livecrawl failed or timed out; a previously cached entry was returned as best-effort. Only occurs when maxAgeHours is not 0. |
statuses[].strategy values
The strategy field records the fetch tier resolved or attempted for the URL.
| Value | Meaning |
|---|---|
"fast" | Content was fetched using the fast HTTP fetch tier. |
"browser" | Content was fetched using the browser-based fetch tier. |
"tls" | Content was fetched using the legacy local non-browser HTTP transport. |
"local-browser" | Content was fetched using the local Playwright-based browser fallback. |
null | No fetch strategy was selected. |
A blocked URL does not produce a status entry: policy rejections fail the whole request with HTTP 451 (see Blocked content).
statuses[].credits values
Credits reflect the fetch strategy used for the URL.
| Strategy | Credits |
|---|---|
"fast" | 1 |
"tls" | 1 |
"browser" | 2 |
"local-browser" | 3 |
| Unresolved | 1 |
| Error | 0 |
Error handling
The endpoint returns HTTP 200 even when individual URLs fail. Per-URL errors appear in the statuses array.
| Tag | HTTP Status | Meaning |
|---|---|---|
CRAWL_NOT_FOUND | 404 | The URL is gone (upstream 404/410), or no cached content was available for a cache-only request (maxAgeHours: -1). |
SOURCE_NOT_AVAILABLE | 403 | The site blocked the crawl (upstream 403/429). |
CRAWL_LIVECRAWL_TIMEOUT | 504 | The livecrawl exceeded the livecrawlTimeout budget. |
CRAWL_NOT_RENDERED | 500 | The page was fetched but produced no usable content (for example an empty or JavaScript-only shell). |
CRAWL_UNKNOWN_ERROR | 500 | An unexpected error occurred during crawling. |
On error, statuses[].error includes:
| Field | Type | Description |
|---|---|---|
error.tag | string | Error type from the table above. |
error.httpStatusCode | integer or null | Corresponding HTTP status code. |
Negative maxAgeHours values
Negative values other than -1 (for example -5) are normalized to -1 and
treated as cache-only. Only 0, -1, and positive values are officially
supported.
Request-level errors
These apply to the request as a whole, not individual URLs.
| HTTP Status | Meaning |
|---|---|
| 400 | Bad request — invalid parameters (for example, more URLs than the request limit). |
| 402 | Insufficient credits (INSUFFICIENT_CREDITS). |
| 403 | Invalid or missing API key. |
| 429 | Rate limit exceeded. |
| 451 | The website is not permitted to be crawled (CRAWL_WEBSITE_NOT_PERMITTED). |
Blocked content
The API does not fetch disallowed content. When any requested URL is blocked, the whole request is rejected with HTTP 451 (CRAWL_WEBSITE_NOT_PERMITTED): no per-URL statuses entry is produced and no credits are charged.
Prohibited Categories
We strictly enforce access restrictions on the following domain types:
- Government & Military Entities:
.gov,.mil, and state/national official administrative portals. - Gambling & Betting Sites: Online casinos, sportsbooks, lotteries, and betting exchanges.
- Illicit & Illegal Content: Platforms hosting illegal goods, dangerous materials, pirated intellectual property, or explicit/exploitative media.
- Google Search & Redirect URLs: Search result and redirect pages.
- Cryptocurrency Mining: Mining pools and related sites.
- Banking & Payment Sites: Banks, payment processors, and financial institutions.
Categories are policy-driven and may change. Blocked attempts are logged for abuse monitoring.
Response Code: 451 Unavailable For Legal Reasons
If a request targets a restricted or blacklisted domain, our API returns an HTTP 451 error status.
Example Error Response
{
"message": "website not permitted",
"timestamp": "2026-01-01T00:00:00.000Z",
"path": "/contents"
}Rate limiting
Our API enforces rate limits to ensure stability and consistent service across all accounts.
The LCR Contents API enforces rate limits based on your subscription plan. Each plan has a maximum number of requests per second (RPS).
If you exceed your plan's rate limit, the API returns a 429 Throttle Exception response.
| Plan | Maximum requests per second (RPS) |
|---|---|
| Starter | 2 RPS |
| Developer | 5 RPS |
| Business | 10 RPS |
| Enterprise | 20 RPS |
| Custom | As agreed |
Note: Your rate limit is determined by your active subscription plan.
- Higher Concurrency: Need greater throughput? Higher dedicated concurrency limits and custom RPS caps are available upon request for enterprise workloads.
Need higher limits? Contact our support team or your account manager to request a concurrency upgrade.

