<!-- twin of https://specstream.ai/migrate/exa-contents -->
# Exa Contents compatible: change the address, $0.80 per 1,000 pages

Compared on Nov 10, 2026. The page: https://specstream.ai/migrate/exa-contents

Exa Contents costs $1 per 1,000 pages for each content type. SpecStream answers the same `POST /contents` in Exa's JSON for $0.80 per 1,000 pages, and a page with no text is not charged.

The switch is one line: `Exa(api_key=KEY, base_url="https://api.specstream.ai/exa")`. The same address answers Exa's search, so one setting moves both.

The Extract API behind this route scores 0.908 F1 on WCXB. Credit you buy never expires, and a new account starts with $10 of credit, no card.

[Get an API key](https://specstream.ai/signup?src=alternatives-migrate-exa-contents&utm_source=alternatives-md&utm_campaign=migrate-exa-contents&returnTo=%2Fworkspace%2Fsearch%3Froute%3Dexa_contents) New accounts get $10 of credit, no card. It covers 2,000 searches.

## Exa Contents to SpecStream, parameter by parameter and field by field

| | SpecStream | Exa Contents |
|---|---|---|
| Address | `POST https://api.specstream.ai/exa/contents` | `POST https://api.exa.ai/contents` |
| The key | A SpecStream key in `x-api-key` or as `Authorization: Bearer` | An Exa key in `x-api-key` or as a Bearer token |
| Pages per call | 1 to 20 in `urls` or `ids`, not both. More than 20 gets Exa's `400` error body | One API call to an endpoint is one request |
| `text` | `true`, or `{"maxCharacters": n}` to cut the text at n characters. Sent when you ask for no content, as exa-py does | The page text is one content type, billed per page |
| Each result | `id`, `url`, `title`, `publishedDate` and `text`. Not returned: `highlights`, `summary`, `image`, `favicon`, `subpages`, `extras` and `entities` | Title, URL, published date and author |
| Errors | Exa's `{requestId, error, tag}`: `401` for a wrong key, `400` for `urls` with `ids`. A busy call gets `429` with `Retry-After` and is not charged | Each page's status in `statuses[]` |
| Price per 1,000 pages | $0.80. A page that gives no text is not charged | $1 per content type |
| Free to start | $10 of credit, no card, which covers 12,500 pages. Credit never expires | $10 in credits on sign up, reset to $10 on the first of every month, no payment method |

## The Exa Contents reference, on SpecStream

### The call, before and after

```
# Before
from exa_py import Exa
exa = Exa(api_key="...")

# After
exa = Exa(api_key=SPECSTREAM_KEY, base_url="https://api.specstream.ai/exa")

reply = exa.get_contents(["https://en.wikipedia.org/wiki/Web_scraping"], text=True)
for result in reply.results:
    print(result.title, result.url, result.text[:300])
```

exa-py 2.28.0 joins `base_url` to `/contents`, so `get_contents` and `search` both reach SpecStream. With no content option exa-py sends `text.maxCharacters`, and the route returns the text cut at that length.

### Apps and SDKs that take the address as a setting

Each line was run on production on November 10, 2026 through that client's own request and reply code. Put your SpecStream key wherever the client takes its key.

Khoj: in the Django admin, set `api_url` on the Exa WebScraper row to `https://api.specstream.ai/exa`. `EXA_API_URL` only fills that row when it is first made.

### What the route reads, and what it refuses

Read and applied: `urls` as one string or a list, `ids` in their place, `text` as `true`, and `text.maxCharacters`. A host that does not resolve is listed in `statuses` with `status` `error` and its tag.

Refused with Exa's error body: more than 20 pages and `urls` sent with `ids` get `400`, and a wrong key gets `401`. Every parameter was measured on production on Nov 10, 2026 with exa-py 2.28.0, and the full [pass table](https://specstream.ai/specstream/dialects/exa_contents.md) lists each one and its result.

### Every field that comes back

The reply has `requestId`, `results[]`, `statuses[]` with `id`, `status`, `source` and `error.tag`, `costDollars.total` with the call's price, and `searchTime` in milliseconds. Each result has `id`, `url`, `title`, `publishedDate` and `text`.

The route does not return `context`, a result's `author`, `highlights`, `highlightScores`, `summary`, `image`, `favicon`, `subpages`, `extras` or `entities`, or a status's `error.httpStatusCode`.

### $0.80 per 1,000 pages

Exa bills $1 per 1,000 pages for each content type a call asks for. On SpecStream every page that gives text costs $0.0008, and a page with no text is not charged. `costDollars.total` on each reply is what the call cost. A busy call gets `429` with `Retry-After` and charges nothing.

### 0.908 F1 on WCXB, and the search scores on the same key

The Extract API that answers this route scores 0.908 F1 on WCXB. The Search API on the same key scores 97.9 F-score on all 1,000 official SimpleQA Verified questions, 978 of them correct, and 64.0 item F1 and 43.4 row F1 on all 200 official WideSearch tasks. Every score and its method is on the [benchmarks](https://specstream.ai/benchmarks?utm_source=alternatives&utm_campaign=migrate-exa-contents) page.

### You decide what is kept, on each key

Create the key with `zero_retention` and a page read made with it keeps no request text and no answer after the reply. `spend_cap_cents` is the most the key can spend.

```
curl -X POST https://api.specstream.ai/v1/account/keys \
  -H "Authorization: Bearer $SPECSTREAM_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "production", "scopes": ["account:read", "finds:spend"], "spend_cap_cents": 500000, "zero_retention": true}'
```

### Search, pages and rows on one key

The same key searches the live web with the [Search API](https://specstream.ai/search-api?utm_source=alternatives&utm_campaign=migrate-exa-contents) at $5 per 1,000 searches of up to 10 results. [Deep Search](https://specstream.ai/deep-search?utm_source=alternatives&utm_campaign=migrate-exa-contents) returns every match for a request in plain words as structured rows, at 5¢, 15¢ or $1 a row, with a source URL on every value. The most a run can cost is approved before it starts. The full comparison is on the [Exa alternative](https://specstream.ai/alternatives/exa?utm_source=alternatives&utm_campaign=migrate-exa-contents) page.

## What else Exa Contents users price

### Tavily Extract

Every 5 successful URL extractions cost 1 credit on basic, at $0.008 a credit on pay as you go, in Tavily's own reply. SpecStream reads 1,000 pages for $0.80 and answers the Exa call your code already sends.

### Firecrawl

A scrape API at 1 credit per page, with the Hobby plan at $19 a month and 1,000 free credits a month. SpecStream needs no plan and keeps Exa's reply shape.

### Jina Reader

Page reads billed in tokens by content length, with 10M free tokens on a new key and no dollar rate on its Reader page. SpecStream charges $0.0008 a page, whatever its length.

## How to migrate, step by step

1. Create a key under Agents & API in the workspace. A new account gets $10 of credit, no card.

2. With exa-py, add `base_url="https://api.specstream.ai/exa"` and the SpecStream key. Without the client, in Python:

```
import requests

reply = requests.post(
    "https://api.specstream.ai/exa/contents",  # was https://api.exa.ai/contents
    headers={"x-api-key": SPECSTREAM_KEY},
    json={"urls": ["https://en.wikipedia.org/wiki/Web_scraping"], "text": True},
    timeout=60,
)
reply.raise_for_status()
data = reply.json()
for result in data["results"]:
    print(result["title"], result["url"], len(result["text"]))
print(data["costDollars"]["total"])
```

3. In JavaScript:

```
const res = await fetch("https://api.specstream.ai/exa/contents", {
  method: "POST",
  headers: { "x-api-key": process.env.SPECSTREAM_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({ urls: ["https://en.wikipedia.org/wiki/Web_scraping"], text: true }),
});
const data = await res.json();
for (const result of data.results) console.log(result.title, result.text.slice(0, 300));
```

4. Check `statuses` for pages that could not be read, and read `429` as a call to send again after `Retry-After`. Neither is charged.

## Frequently asked questions

### Is there an Exa Contents compatible API?

Yes. SpecStream answers Exa's `POST /contents` at `https://api.specstream.ai/exa` in Exa's JSON, as measured on production on Nov 10, 2026 with exa-py 2.28.0. It costs $0.80 per 1,000 pages.

### How do I migrate from Exa Contents?

Change one line: `Exa(api_key=KEY, base_url="https://api.specstream.ai/exa")`. Without the client, post the same body to `https://api.specstream.ai/exa/contents` with a SpecStream key in `x-api-key`.

### How much does Exa Contents cost?

$1 per 1,000 pages for each content type, with $10 of free credits that reset on the first of every month. SpecStream costs $0.80 per 1,000 pages, and a page with no text is not charged.

### Which apps and SDKs take the SpecStream address for Exa Contents?

Khoj: in the Django admin, set `api_url` on the Exa WebScraper row to `https://api.specstream.ai/exa`. `EXA_API_URL` only fills that row when it is first made.

### Can I change the address in exa-py?

Yes, with `base_url`, tested with exa-py 2.28.0 on Nov 10, 2026. The client joins it to `/contents` and `/search`, so both calls move together.

### How many pages can one call read?

Up to 20 in `urls` or `ids`. A call with more gets `400` in Exa's error body; send the rest in a second call.

### Which Exa Contents fields does SpecStream not return?

`highlights`, `summary`, `image`, `favicon`, `subpages`, `extras`, `entities` and `author` on a result, and `context` on the reply. Each result has `id`, `url`, `title`, `publishedDate` and `text`.

## Sources

SpecStream wrote this page. Each Exa figure comes from Exa's own pages, and each other provider's figure from that company's own page. The route's behavior comes from its code and the pass table measured on production.

- [Exa pricing](https://exa.ai/docs/admin/pricing.md), read Nov 10, 2026
- [Exa search reference](https://exa.ai/docs/reference/search.md), read Nov 10, 2026
- [SpecStream Exa Contents pass table](https://specstream.ai/specstream/dialects/exa_contents.md), read Nov 10, 2026
- [Tavily API credits](https://docs.tavily.com/documentation/api-credits.md), read Nov 10, 2026
- [Firecrawl pricing](https://www.firecrawl.dev/pricing), read Nov 10, 2026
- [Jina Reader](https://jina.ai/reader), read Nov 10, 2026
- [SpecStream benchmarks](https://specstream.ai/benchmarks), read Nov 10, 2026
- [SpecStream pricing](https://specstream.ai/pricing), read Nov 10, 2026
- [SpecStream for agents](https://specstream.ai/agents.md), read Nov 10, 2026
