Providers

Jina

Jina's s.jina.ai for search and r.jina.ai for reading, the default reader, with an optional key.
IDjina05 / 13s.jina.ai, r.jina.ai
Provider

Jina

  • create("jina")
  • JINA_API_KEY
Auth
Bearer header, optional for read
Results
10, up to 20 · one page
Free tier
key required for search, optional for read

Capabilities

Options

FiltersincludeDomains, category
FieldspublishedDate, image, text, metadata
Categoryweb, images, news
Readmarkdown, text, html · format, maxTokens, targetSelector, removeSelector, timeout, noCache

Address it

ts
import { create, readUrl } from "@agntn/web";

const jina = await create("jina"); // JINA_API_KEY, required for search
const results = await jina.search("model context protocol", { category: "news" });
const page = await readUrl("https://modelcontextprotocol.io", { format: "markdown" }); // Jina first, no key needed

The key is sent as a Bearer token. Search needs it, reading works without one and sends it when present.

What it reads

CallEndpoint
searchGET https://s.jina.ai/… with Accept: application/json
readGET https://r.jina.ai/<url> with X-Return-Format, X-Target-Selector, X-Remove-Selector, X-Timeout, X-No-Cache

The reader host is derived from the search host, so a custom baseURL for s. moves r. with it.

What comes back

Search results carry the page content in text, plus publishedDate, image and metadata. includeDomains and a category of web, images or news work. Reads give markdown, text or html and take maxTokens natively, as a budget: a longer page fails with a 409 instead of coming back cut.

Gotchas

  • Without a key r.jina.ai is rate limited per address. With a key, an empty balance answers 402, which is eligible for fallback to the next configured reader.
  • A 409 from the reader (could not fetch the page right now) is eligible for fallback too.
  • text on search results is the whole page. Ten results can be huge, keep maxResults low.

Where it lives

src/providers/jina.ts, the template for a reader.