Skip to main content

Contents Endpoint Reference

Known-URL extraction surface via POST /contents.
  • Base docs URL: https://exa.ai/docs
  • Contents reference: /reference/get-contents
  • Contents coding-agent reference: /reference/contents-api-guide-for-coding-agents
  • Contents best practices: /reference/contents-best-practices
  • Content freshness: /reference/livecrawling-contents

Contents

  • Overview
  • Request shape
  • Top-level content fields
  • Freshness controls
  • Response and statuses
  • Critical pitfalls

Overview

Use the contents endpoint when:
  • you already know the URLs
  • you need clean extraction without first running a search query
  • freshness and crawl behavior matter enough to control directly
  • you want the search endpoint and contents endpoint separated into two explicit calls

Request Shape

POST https://api.exa.ai/contents
{
  "urls": ["https://arxiv.org/abs/2307.06435"],
  "highlights": {
    "query": "methodology"
  }
}

Core Request Parameters

ParameterTypeNotes
urlsstring[]Primary way to pass known URLs
idsstring[]Backwards-compatible alias for document IDs from prior Exa calls
textboolean or objectTop-level text extraction control
highlightsboolean or objectTop-level highlights extraction control
summaryboolean or objectTop-level summary extraction control
maxAgeHoursintegerNormative freshness control
livecrawlTimeoutintegerTimeout in milliseconds
subpagesintegerCrawl linked subpages
subpageTargetstring or string[]Focus which subpages to crawl
extrasobjectExtra link and image extraction

Top-Level Content Fields

This is the most important shape difference in the Exa platform:
  • on the search endpoint, content fields are nested inside contents
  • on the contents endpoint, text, highlights, and summary are top-level request fields
from exa_py import Exa

exa = Exa(api_key="YOUR_EXA_API_KEY")
result = exa.get_contents(
    ["https://docs.exa.ai"],
    highlights=True
)

Content Field Behavior

FieldBest ForNotes
textFull extractionSupports maxCharacters, includeHtmlTags, verbosity, includeSections, excludeSections
highlightsToken-efficient excerptsGood default for agent pipelines
summaryPer-page compressionEach page adds its own synthesis step, so use only when you explicitly need Exa-side summaries
Pick one of text, highlights, or summary by default. Stacking them is unnecessary. summary adds a per-page LLM call, and combining text with highlights increases billing for two views of the same page.

Freshness Controls

Use maxAgeHours as the normative control for new integrations:
ValueBehavior
omittedDefault behavior; cached content first, crawl fallback when needed
positive integerAccept cache up to that age, then live crawl
0Always live crawl
-1Cache only
Set livecrawlTimeout whenever live crawling matters so slow pages do not block the whole request longer than expected. Do not send livecrawl and maxAgeHours together; prefer maxAgeHours in new requests and examples.

Response and Statuses

The contents endpoint can return HTTP 200 even when some requested URLs fail. Always inspect statuses.
{
  "results": [
    {
      "url": "https://example.com",
      "text": "..."
    }
  ],
  "statuses": [
    { "id": "https://example.com", "status": "success" },
    { "id": "https://bad.example", "status": "error" }
  ]
}
Common status/error tags include crawl timeout, unsupported URL, source unavailable, and not found conditions. Treat statuses as part of normal control flow, not as a rare exception path.

Critical Pitfalls

  1. Do not wrap text, highlights, or summary inside a contents object on /contents.
  2. Do not assume HTTP 200 means every URL succeeded; inspect statuses.
  3. Do not add stream: true; the contents endpoint does not support streaming.
  4. Prefer maxAgeHours over older livecrawl strings in new examples.
  5. In Python SDK calls, remember snake_case inside nested options such as max_characters and max_age_hours.
Last modified on June 26, 2026