exa-contents
Skill33 starsChanged 6 months agoMITView on GitHub
Call Exa Contents (POST /contents) for LLM-ready extraction from known URLs: text, highlights, summaries, links, image links, subpages, freshness-controlled crawl. Use when the agent already has URLs. Prefer Exa MCP web_fetch_exa when available; otherwise raw HTTP with EXA_API_KEY. NOT for open-ended discovery (use exa-search) or auth-walled X/Twitter (use mktg-x). For full-site crawl of a known domain, firecrawl may be better.
- Reads credentials
- Sends data out
We split this skill into the rules it gives an agent
18 rules. About 0 are common, 1 is distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 26
Read brand/competitors.md / brand/landscape.md if present for URL shortlists.
- Very specific: line 28
Prefer MCP web_fetch_exa when available.
- Very specific: line 29
If the page is auth-walled (X/Twitter login stub), route to mktg-x instead.
- Very specific: line 37
Use POST https://api.exa.ai/contents when the agent already knows the URLs and needs clean, LLM-ready extraction without running a new …
- Very specific: line 77
Use this endpoint for known-URL extraction.
- Very specific: line 109
Prefer highlights: true for the highest-quality default.
- Distinctive: line 133
Avoid requesting multiple modes unless the caller truly needs multiple views of the same page.
- Very specific: line 137
Use maxAgeHours as the normative freshness control.
- Very specific: line 150
Use subpages and subpageTarget when linked pages matter.
- Very specific: line 170
Start with subpages around 5 to 10, then increase only when the caller needs broader site coverage.
- Very specific: line 210
Keep text, highlights, and summary at the top level on /contents.
- Very specific: line 211
Do not wrap extraction options in a contents object.
- Very specific: line 212
Do not assume HTTP 200 means every URL succeeded.
- Very specific: line 213
Do not send stream: true; /contents is not a streaming endpoint.
- Very specific: line 214
Do not send tokensNum; use text.maxCharacters to cap extracted text.
- Very specific: line 215
Do not use useAutoprompt, numSentences, highlightsPerUrl, or older livecrawl string values in new requests.
- Very specific: line 216
Prefer maxAgeHours for freshness and pair it with livecrawlTimeout when crawl latency matters.
- Very specific: line 217
Use subpageTarget with subpages.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
On Activation
- Read
brand/competitors.md/brand/landscape.mdif present for URL shortlists. Optional. - Confirm Exa auth (MCP or
EXA_API_KEY) viamktg doctorif unsure. - Prefer MCP
web_fetch_exawhen available; otherwise use the cURL examples below. - If the page is auth-walled (X/Twitter login stub), route to
mktg-xinstead.
Exa Contents
Requires API key: Get one at https://dashboard.exa.ai/api-keys
Header:
x-api-key: $EXA_API_KEY
Use POST https://api.exa.ai/contents when the agent already knows the URLs and needs clean, LLM-ready extraction without running a new search. Start with one content mode: highlights for compact agent context, text for broad page context, or summary for Exa-side compression.
Quick Start (cURL)
Basic text extraction
curl -sS -X POST "https://api.exa.ai/contents" \
-H "Content-Type: application/json" \
-H "x-api-key: $EXA_API_KEY" \
-d '{
"urls": ["https://example.com"],
"text": true
}'Highlights with freshness control
curl -sS -X POST "https://api.exa.ai/contents" \
-H "Content-Type: application/json" \
-H "x-api-key: $EXA_API_KEY" \
-d '{
"urls": ["https://arxiv.org/abs/2307.06435"],
"highlights": {
"query": "methodology and results"
},
"maxAgeHours": 24,
"livecrawlTimeout": 12000
}'Endpoint
POST https://api.exa.ai/contentsAuthentication: x-api-key: <API_KEY> header. Exa also accepts Authorization: Bearer <API_KEY>, but prefer x-api-key in cURL examples for consistency.
Use this endpoint for known-URL extraction. If the agent needs discovery or ranking first, use POST /search.
Parameters
Core request parameters
| Parameter | Type | Required | Default | Description |
urls | string[] | Yes | - | URLs to extract content from. Use this for known URLs. |
text | boolean or object | No | - | Return full page text as markdown. Object form supports maxCharacters, includeHtmlTags, verbosity, includeSections, and excludeSections. |
highlights | boolean or object | No | - | Return key excerpts. Prefer true for agent workflows unless a custom focus is needed. |
summary | boolean or object | No | - | Return per-page LLM summaries. Use when the caller wants Exa-side compression or structured extraction. |
maxAgeHours | integer | No | - | Freshness control. 0 always live crawls; -1 uses cache only; omit for default cache-first behavior with crawl fallback. |
livecrawlTimeout | integer | No | 10000 | Timeout for live crawling in milliseconds. Use 10000 to 15000 for most freshness-sensitive calls. |
subpages | integer | No | 0 | Number of linked subpages to crawl from each URL. |
subpageTarget | string or string[] | No | - | Terms used to prioritize which subpages matter, such as ["api", "reference", "pricing"]. |
extras.links | integer | No | 0 | Number of links to extract from each page. |
extras.imageLinks | integer | No | 0 | Number of image URLs to extract from each page. |
compliance | string | No | - | Enterprise-only compliance mode, such as hipaa, when enabled for the account. |
Text object options
| Parameter | Type | Default | Description |
maxCharacters | integer | - | Character limit for returned text. Use this instead of tokensNum. |
includeHtmlTags | boolean | false | Preserve HTML tags in output. |
verbosity | string | compact | compact, standard, or full. Pair fresh section-aware extraction with maxAgeHours: 0. |
includeSections | string[] | - | Only include selected sections: header, navigation, banner, body, sidebar, footer, metadata. |
excludeSections | string[] | - | Exclude selected sections from the same section list. |
Highlights object options
Prefer highlights: true for the highest-quality default. Only use object form when the agent needs a custom focus or budget.
| Parameter | Type | Default | Description |
query | string | - | Custom query guiding which excerpts are returned. |
maxCharacters | integer | - | Cap highlight characters per URL. Omit unless the caller has a strict budget. |
Summary object options
| Parameter | Type | Default | Description |
query | string | - | Custom query for the summary. |
schema | object | - | JSON Schema for structured per-page summaries. |
Content Modes
On /contents, text, highlights, and summary are top-level request fields.
| Mode | Best for | Notes |
text | Deep analysis and broad page context | Use maxCharacters to keep payloads bounded. |
highlights | Agent workflows and factual lookups | Most token-efficient default. Excerpts are grounded in the source page. |
summary | Compression or structured per-page extraction | Adds Exa-side synthesis per page. |
Avoid requesting multiple modes unless the caller truly needs multiple views of the same page.
Freshness and Crawling
Use maxAgeHours as the normative freshness control.
| Value | Behavior |
| omitted | Use default cache-first behavior with crawl fallback when needed. |
| positive integer | Use cache if it is less than N hours old, otherwise live crawl. |
0 | Always live crawl. Highest freshness, higher latency. |
-1 | Cache only. Fastest, but fails if no cached content exists. |
Set livecrawlTimeout when live crawling should not block past a fixed budget.
Subpages and extras
Use subpages and subpageTarget when linked pages matter.
curl -sS -X POST "https://api.exa.ai/contents" \
-H "Content-Type: application/json" \
-H "x-api-key: $EXA_API_KEY" \
-d '{
"urls": ["https://docs.example.com"],
"text": {
"maxCharacters": 5000
},
"subpages": 10,
"subpageTarget": ["api", "reference", "guide"],
"extras": {
"links": 10,
"imageLinks": 5
}
}'Start with subpages around 5 to 10, then increase only when the caller needs broader site coverage.
Response Fields and Statuses
Inspect statuses even when the HTTP status is 200. The endpoint can succeed for one URL and fail for another in the same request.
curl -sS -X POST "https://api.exa.ai/contents" \
-H "Content-Type: application/json" \
-H "x-api-key: $EXA_API_KEY" \
-d '{
"urls": ["https://example.com", "https://bad.example"],
"highlights": true
}' | jq '{results, statuses}'| Field | Type | Description |
requestId | string | Unique request identifier. |
results | array | Extracted content result objects. |
results[].title | string | Page title. |
results[].url | string | Page URL. |
results[].publishedDate | string or null | Estimated publication date when available. |
results[].author | string or null | Author when available. |
results[].text | string | Returned when text is requested. |
results[].highlights | string[] | Returned when highlights is requested. |
results[].highlightScores | number[] | Similarity scores for highlights. |
results[].summary | string | Returned when summary is requested. |
results[].subpages | array | Nested result objects from subpage crawling. |
results[].extras.links | string[] | Extracted links when requested. |
statuses | array | Per-URL success or error states. Always inspect this field. |
statuses[].id | string | Requested URL. |
statuses[].status | string | success or error. |
statuses[].error.tag | string | Error type for failed URLs. |
statuses[].error.httpStatusCode | integer or null | HTTP code associated with a per-URL failure. |
costDollars.total | number | Total request cost when returned. |
Common per-URL error tags include CRAWL_NOT_FOUND, CRAWL_TIMEOUT, CRAWL_LIVECRAWL_TIMEOUT, SOURCE_NOT_AVAILABLE, UNSUPPORTED_URL, and CRAWL_UNKNOWN_ERROR.
Anti-Patterns
- Keep
text,highlights, andsummaryat the top level on/contents. - Do not wrap extraction options in a
contentsobject; that nesting belongs to/search. - Do not assume HTTP 200 means every URL succeeded; inspect
statuses. - Do not send
stream: true;/contentsis not a streaming endpoint. - Do not send
tokensNum; usetext.maxCharactersto cap extracted text. - Do not use
useAutoprompt,numSentences,highlightsPerUrl, or olderlivecrawlstring values in new requests. - Prefer
maxAgeHoursfor freshness and pair it withlivecrawlTimeoutwhen crawl latency matters. - Use
subpageTargetwithsubpages; otherwise subpage selection is best effort. - Pick one of
highlights,text, orsummaryby default. Stack modes only when the caller truly needs multiple views of each page.
Attribution
Ported from exa-labs/agent-skills - adapted for mktg's drop-in contract on 2026-07-18.
Upstream commit: 390ffee2d7e1d0dce2ed8efe4994c2b3c1c0173b
Drift detection: if the upstream skill changes, re-run mktg-steal https://github.com/exa-labs/agent-skills to evaluate the diff.
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 1
- exa-labs/agent-skills★ 6595% same
Wrote their own version · 1
- jackmazac/exa-cli★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository79 other files it gives its agents.
- AGENTS.mdAGENTS.md
- studio/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- studio/CLAUDE.mdCLAUDE.md
- agent-email-inboxSkill
- ai-seoSkill
- app-store-screenshotsSkill
- audience-researchSkill
- axiSkill
- brainstormSkill
- brand-kit-playgroundSkill
- brand-voiceSkill
- build-with-exaSkill
- churn-preventionSkill
- cmo-remotionSkill
- cmoSkill
- company-researchSkill
- competitive-intelSkill
- competitor-alternativesSkill
- content-atomizerSkill
- conversion-flow-croSkill
- create-skillSkill
- creativeSkill
- deepen-planSkill
- direct-response-copySkill
- document-reviewSkill
- email-sequencesSkill
- exa-searchSkill
- firecrawlSkill
- free-tool-strategySkill
- frontend-slidesSkill
- higgsfield-generateSkill
- higgsfield-product-photoshootSkill
- higgsfield-soul-idSkill
- image-genSkill
- keyword-researchSkill
- landscape-scanSkill
- launch-strategySkill
- lead-generationSkill
- lead-magnetSkill
- manimce-best-practicesSkill
- manim-composerSkill
- manimgl-best-practicesSkill
- marketing-demoSkill
- marketing-psychologySkill
- mktg-setupSkill
- mktg-xSkill
- newsletterSkill
- off-page-seoSkill
- openseo-coachSkill
- openseo-competitive-landscapeSkill
- openseo-competitor-analysisSkill
- openseo-keyword-clusteringSkill
- openseo-keyword-researchSkill
- openseo-link-prospectingSkill
- openseo-project-setupSkill
- openseoSkill
- page-croSkill
- paper-marketingSkill
- positioning-anglesSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

