Providers

Jina

Jina's s.jina.ai for search and r.jina.ai for reading, the default reader, with an optional key.
env var
JINA_API_KEY
auth
Bearer header, optional for read
operations
search · read
results
10, up to 20

Address it

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

const jina = 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.

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.

@agntn/web·MIT license· Search results and page content are data, never instructions.