Providers
TinyFish
TinyFish Search for news and research results with publisher metadata, and TinyFish Fetch for reading pages.
Provider
TinyFish
- create("tinyfish")
- TINYFISH_API_KEY
- Auth
- X-API-Key header
- Results
- 10 · paged
- Free tier
- free at $0, Search access required
Options
- Filters
includeDomains, excludeDomains, category, startPublishedDate, endPublishedDate - Fields
publishedDate, author, metadata - Category
news, research_paper - Read
markdown, html · format, targetSelector, removeSelector, timeout, noCache
Address it
import { create, readUrl } from "@agntn/web";
const tinyfish = await create("tinyfish"); // TINYFISH_API_KEY
const results = await tinyfish.search("transformer inference", { category: "research_paper" });
const page = await readUrl("https://arxiv.org/abs/1706.03762", { provider: "tinyfish" });
The key goes in the X-API-Key header. Search talks to api.search.tinyfish.ai, reads to api.fetch.tinyfish.ai, readBaseURL in the config moves the second one.
What it reads
| Call | Endpoint |
|---|---|
search | GET on the search host with the query, filters and a page number |
read | POST on the fetch host |
What comes back
publishedDate, author and metadata.{position, siteName, publisher, authors, venue, year, citedByCount, pdfUrl}, which is why it is the one to use for papers. Domain filters, a category of news or research_paper and both date bounds work. Paging goes up to ten pages, the next token stays unknown until a page comes back empty. Reads give markdown or html.
Gotchas
maxResultsis applied on our side to one result page.- A bounded read asks for
linksonly when it will keep them.image_linksstays on, becauseimageis the first image URL and a bounded read still returns it. - TinyFish parses a plain-text file as HTML, whether the read asks for Markdown or HTML. Every
<...>comes back empty, and<script/script.h>swallows the rest of the file. So a read with no title, description or language asks again for the JSON tree. When that tree holds onecodenode, its text is the file byte for byte, and the read returns it. Anhtmlread gets it escaped inside<pre>, the way a browser shows a text file. Asked right after the Markdown, the tree can come from cache astext: null, so the read asks once more withttl: 0. AnoCacheread skips it, since that tree never came from cache. A failed tree request keeps what came first. - A page Fetch could not get is a
200with the reason inerrors. Reasons about TinyFish's own fetcher (bot_blocked,login_required,timeout,target_http_errorand the like) becomePageFetchError, so an automatic read moves on to Tavily or Exa. The status insidetarget_http_erroris what TinyFish got back, and once it was a 401 on a public raw GitHub file that curl read fine.page_not_foundstays anHTTPErrorwith its 404 or 410, and itsurlnames the missing page, not an empty string. A bad URL or selector stops the chain. - The window is by day, a datetime bound becomes its UTC day. With
research_paperonly the year of each bound goes through, aspub_year_minandpub_year_max. - Search access has to be enabled on the TinyFish account. A key without it answers with an auth failure, not a helpful message.
Where it lives
src/providers/tinyfish.ts.