# Jina Reader's calls against SpecStream

Date: 2026-11-10. Client: Jina's documented curl calls (Jina publishes no Reader client library) as documented on jina.ai/reader.

## The one line a user changes

Before:

```
curl -X POST https://r.jina.ai/ -H "Authorization: Bearer $JINA_API_KEY" -d "url=$URL"
```

After:

```
curl -X POST https://api.specstream.ai/jina -H "Authorization: Bearer $KEY" -d "url=$URL"
```

The address form `https://r.jina.ai/<url>` is not served: send the page as `url` in the body, as Jina's POST form does.

## Request parameters

Honoured means the check in the Measured column passed on the reply. Accepted, not applied means status 200 and the reply has the form of the same call without the parameter. Refused means the vendor's error body and status.

Counts: 6 honoured, 25 accepted, not applied, 3 refused.

| Parameter | Sent | Verdict | Measured |
|---|---|---|---|
| `url (form body)` | `url=https://en.wikipedia.org/wiki/Web_scraping` | honoured | status 200; reply starts with Title: |
| `url (JSON body)` | `{"url": "https://en.wikipedia.org/wiki/Web_scraping"}` | honoured | status 200; reply starts with Title: |
| `Accept: application/json` | header | honoured | status 200; data.content holds the page |
| `X-Return-Format: text` | header | honoured | status 200; the page's text with no Title: head |
| `X-Return-Format: text with JSON` | headers | honoured | status 200; data.text holds the page |
| `X-Return-Format: markdown` | header | honoured | status 200; Markdown Content: section |
| `X-Return-Format: html` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Return-Format: screenshot` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Return-Format: pageshot` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Respond-With: readerlm-v2` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Target-Selector: main` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Remove-Selector: nav` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Wait-For-Selector: main` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Timeout: 10` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-No-Cache: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Cache-Tolerance: 60` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-With-Links-Summary: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-With-Images-Summary: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Retain-Images: none` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-With-Generated-Alt: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Engine: direct` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Token-Budget: 50000` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Locale: en-US` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Set-Cookie: a=b` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Proxy: us` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Robots-Txt: SpecStream` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-With-Iframe: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-With-Shadow-Dom: true` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `X-Md-Heading-Style: setext` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `DNT: 1` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `Accept: text/event-stream` | header | accepted, not applied | status 200; reply has the baseline's text form |
| `Authorization` | absent | refused | status 401; AuthenticationFailedError |
| `url` | absent | refused | status 400; ParamValidationError |
| `url (a host that does not resolve)` | `url=https://nonexistent-xyz-host-qq.example` | refused | status 422; SubmittedDataMalformedError |

## Response fields

Present means the field holds a value in the replies to the calls above. Empty means it is there with no value. Absent means it is not in the reply.

Counts: 12 present, 0 empty, 12 absent.

| Field | State | Measured |
|---|---|---|
| `code` | present | JSON replies (Accept: application/json) |
| `status` | present | JSON replies (Accept: application/json) |
| `data.title` | present | JSON replies (Accept: application/json) |
| `data.url` | present | JSON replies (Accept: application/json) |
| `data.content` | present | JSON replies (Accept: application/json) |
| `data.text` | present | JSON replies (Accept: application/json) |
| `data.publishedTime` | present | JSON replies (Accept: application/json) |
| `data.description` | absent | JSON replies (Accept: application/json) |
| `data.finalUrl` | absent | JSON replies (Accept: application/json) |
| `data.warning` | absent | JSON replies (Accept: application/json) |
| `data.metadata` | absent | JSON replies (Accept: application/json) |
| `data.external` | absent | JSON replies (Accept: application/json) |
| `data.httpStatus` | absent | JSON replies (Accept: application/json) |
| `data.httpStatusText` | absent | JSON replies (Accept: application/json) |
| `data.usage.tokens` | absent | JSON replies (Accept: application/json) |
| `data.links` | absent | JSON replies (Accept: application/json) |
| `data.images` | absent | JSON replies (Accept: application/json) |
| `meta.usage.tokens` | absent | JSON replies (Accept: application/json) |
| `text form Title:` | present | default text reply |
| `text form URL Source:` | present | default text reply |
| `text form Published Time:` | present | default text reply |
| `text form Warning:` | absent | default text reply |
| `text form Markdown Content:` | present | default text reply |
| `Content-Type of the text form` | present | text/html; charset=utf-8 (r.jina.ai sends text/plain) |
