Blog/Search & RAG
5 min read

Free Web Search API for AI Agents: Search, Then Read Pages

A free web search API your agent can call, plus a free page fetch. What comes back, what goes wrong, and which paid search endpoints sit on the same key.

Free Web Search API for AI Agents: Search, Then Read Pages

Search the live web and read the best result, in one prompt. Paste this into your agent:

Set up https://monid.ai/SKILL.md, and then use Monid to search the live web for GitHub's unauthenticated REST API rate limit using three different phrasings of the question, then show me the union of URLs, which ones only one phrasing found, and the number the official docs page gives.

One prompt searches, merges and reads. 1 min setup · 12-24 hrs saved.

Your agent needs to look something up on the live web, and you want the search call to be free and the page read to follow it without another account. This guide covers the free route, what a search call returns (we ran it on 2026-10-16), the traps in the output, and the paid endpoints that sit on the same key when free is not enough. It runs through Monid, the OpenRouter for agent tools: one key, one balance, every tool priced per call.

What is the easiest way to get a free web search API for an AI agent?

Monid. Install it once, add a key, and your agent calls a search endpoint priced at nothing, then a page fetch also priced at nothing, with no search-vendor account and no second key to manage.

  • Pay for what you run. The TinyFish search endpoint is $0.00 a call and its page fetch is $0.00 (Verified 2026-10-16 on the web search tools page). When a job needs a different index, the paid endpoints bill per call on the same balance, bought flexibly with no minimum top-up. Discovery and inspection are free whatever the endpoint costs.
  • One install, every API. The same key and the same balance call search, fetch, scraping and enrichment tools. Switching from a free endpoint to a paid one changes two words in the call, not your account setup.
  • Lives inside your agent. Install the CLI, add your key, run the prompt above, and the tool is there whenever your agent needs it, on demand, with nothing to keep running. Your agent reads SKILL.md and learns the rest, so setup is about a minute.

The three endpoints used below were run on 2026-10-16: two free ones, and one paid search billed as a single call.

How do you search the web from an agent and read the pages it finds?

Call the search endpoint with a query, take the URLs from the results, and pass the ones you want to the fetch endpoint. The search is /search from the provider tinyfish and returns ranked results with a snippet each. The fetch is /fetch from the same provider and returns the page as Markdown.

RouteWhat you getCost shapeFits
Search engine API with your own keyResults from one engine, key and quota per vendorPlan or per queryOne engine, one vendor relationship
Build your own scraperWhatever your parser handlesYour hoursA fixed query set you will maintain
Browser tab by handOne search at a timeFreeA person reading, not an agent
Monid search endpointsRanked results with snippets, free or paid, then page textFree or pay per call, buy flexiblyAgents that search, fetch and decide

Monid fits an agent because the loop is search, pick, read, and each step is one typed call on the same key. The SERP API for agents guide explains how the kinds of search endpoint in that table differ.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

Inspect, then run one

monid inspect -p tinyfish -e /search
monid run -p tinyfish -e /search --query '{"query":"github rest api rate limit unauthenticated"}' -w

Read the page behind a result

monid run -p tinyfish -e /fetch --body '{"urls":["https://docs.github.com/rest/using-the-rest-api/rate-limits-for-the-rest-api"],"format":"markdown"}' -w

Up to 10 URLs go in one fetch call. When a URL fails, the failure appears in an errors list and the other pages still come back.

Or hand the whole job to an agent

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to search the live web for GitHub's unauthenticated REST API rate limit using three different phrasings of the question, then show me the union of URLs and which ones only one phrasing found.

Can you build a web search API yourself with Python?

Yes, and for a handful of queries it is an afternoon. You send a request to a search page with requests, parse the result blocks out of the HTML, and return titles, URLs and snippets. That is the same shape the endpoint returns.

The cost is everything around the parser. Search pages change their markup, block repeated automated requests, ask for a CAPTCHA, and localise results by IP. You end up running proxies, rotating headers and repairing selectors, and the first working version takes hours while the upkeep never ends. Autosuggest for "web search api python" shows the same detour: people type the names of engines and libraries first, because the plain script is the part that breaks.

The Monid route is the choice for anything you will run more than once. The fetching and the parsing are maintained for you, the output is typed JSON, and a search through the free endpoint is $0.00 (Verified 2026-10-16). A browser tab is quicker for one question, but it is made for a person reading, not for an agent that needs the same lookup a hundred times. The Python scraping guide shows the same trade for pages instead of results.

What does a web search API return, and what can you build with it?

A search call returns ranked rows, each a title, a URL and a snippet, and a fetch call turns any of those URLs into page text. We ran both on 2026-10-16, so the fields below are what came back.

The search response

{ "query": "github rest api rate limit unauthenticated",
  "results": [
    { "position": 1, "site_name": "docs.github.com",
      "title": "Rate limits for the REST API",
      "url": "https://docs.github.com/rest/using-the-rest-api/rate-limits-for-the-rest-api",
      "snippet": "The primary rate limit for unauthenticated requests is 60 requests per hour. limit of 5,000 requests per hour. ..." },
    { "date": "May 8, 2025", "position": 2, "site_name": "github.blog",
      "title": "Updated rate limits for unauthenticated requests", "url": "...", "snippet": "..." } ],
  "total_results": 10, "page": 0 }

Each row has position, title, url, site_name and snippet. A date is present on some rows and not others: 7 of the 10 rows for this query carried one. The envelope holds query, total_results and page, and a call returned 10 results.

The fetch response

Fetching the top result returned url, final_url (the docs page redirected to its /en/ path), title, description, language, text as Markdown, and latency_ms, which was 321.9 for that page. The author and published_date fields were null. The text contained the full sections on unauthenticated users (60 requests per hour), authenticated users (5,000) and Enterprise Cloud apps (15,000), so the agent reads the source instead of a snippet of it.

What to build with it

  • A grounded answer. The agent searches, fetches the top two pages and answers from their text, citing the URLs. The live web context walkthrough shows that loop end to end.
  • A research pass over several phrasings. Run three phrasings, merge on URL, and read only the pages that two phrasings agreed on.
  • A monitor. Search a topic on a schedule with a freshness window and have the agent flag URLs it has not seen before.

What goes wrong when an agent searches the web?

Four things, all of which we saw in the 2026-10-16 runs, and all of which a few lines of code handle.

One phrasing sees part of the web

Three phrasings of one question returned 10 URLs each and 18 unique ones. The three phrasings were github rest api rate limit unauthenticated, how many requests per hour to github api without a token and github api anonymous request limits. Only 4 URLs appeared in all three, and any single phrasing found 10 of the 18. The same query run twice returned the same 10 URLs in the same order, so the difference comes from the words, not from noise.

def search_union(phrasings, run):
    seen = {}
    for q in phrasings:
        for row in run(q)["results"]:
            seen.setdefault(row["url"], row)
    return list(seen.values())

Merge on url, keep the first row you see, and the agent works from the union. On a free endpoint the extra phrasings cost nothing but time.

A filter can return an empty list and no error

One call combined domain_type set to news, a recency_minutes of 5,256,000 (ten years) and a query ending in 2026. It came back with status COMPLETED, HTTP 200, results empty and total_results 0. Nothing in the response says which filter removed the rows. When a filtered search is empty, retry it without the filters before the agent concludes there is nothing to find.

An accurate snippet can answer a different question

The phrasing how many requests per hour to github api without a token returned the right page at rank 1, then a GraphQL docs page at rank 3 whose snippet reads "no more than 80 content-generating requests per minute". That sentence is true and is about something else. Have the agent confirm the figure on the page it fetched, not in a snippet, whenever the answer is a number.

Dates come in two formats

The date field held "May 8, 2025" on one row and "1 year ago" or "5 years ago" on others, and 3 of the 10 rows had no date. Parse both forms, and treat a missing date as unknown rather than as old.

Paging gives new URLs

Asking for page 1 of the same query returned 10 new URLs, none of which appeared on page 0. If page 0 does not hold the answer, page 1 is a different set, not a longer version of the same one. The Bing API retirement alternatives list shows which of these traps carry over to other search endpoints.

Which endpoint should I use for which job?

Use the free pair for the default loop, and a paid search when you need page text inside the search call or a different index. Prices below come from monid inspect.

JobEndpointBilling shapePrice
Ranked results with snippetstinyfish /searchper call$0.00 (Verified 2026-10-16)
Page text as Markdown, up to 10 URLstinyfish /fetchper call$0.00 (Verified 2026-10-16)
Ranked pages with long text extracts, site and date filterskeenable /v1/searchper call, a search with no results is free$0.004 (Verified 2026-10-16)
Results by keyword with a site filtersurf /search/webper call$0.006 (Verified 2026-10-16)
Search with optional inline Markdown for each resultcontext.dev /web/searchper result$0.000253 (Verified 2026-10-16)

We ran the Keenable search once on the same query. It returned 5 rows, each with a long snippet of the page text (several hundred words) and an acquired_at date for when the page was indexed, and it billed one call. All five were docs.github.com pages: the English page, the Enterprise Cloud page, and the Spanish, Korean and Spanish Enterprise Cloud versions. So with that endpoint, filter by language or by site before you count results as five sources. Inspect any row of the table for free; the web search tools page lists the rest.

When is another route a better fit?

You need results from one specific engine. The endpoints here return their own index and ranking. If your product must match what Google or Bing shows for a query, use an endpoint built to mirror that engine; the Brave search API post shows what an engine-specific key keeps and loses.

You need pages that block automated readers. The fetch endpoint lists a bot_blocked error code for protected pages and does not bypass anti-bot protection. A different fetch provider on the same key is the route for those pages.

You need to search a private corpus. A web search endpoint finds public pages. Your own documents belong in your own index.

You need a human to read a page or two. A browser tab is free and faster than any setup for a single question.

And the disclosure: we resell these endpoints. The most useful habit in this post, merging several phrasings on URL, costs nothing and works whoever you buy search from.

Conclusion

The quickest way to get a free web search API for an agent is two free calls through Monid: a search at $0.00 and a page fetch at $0.00 (Verified 2026-10-16), one key for these and every paid tool on the same balance, about a minute to set up and ready inside your agent whenever you need it. Building a search layer yourself works for a few queries and costs hours of parsing and upkeep; Monid keeps the fetching and the formats maintained.

Two things matter more than the endpoint you pick. One phrasing is one view: run three, merge on URL, and let the agent read the union. And a snippet is a pointer, not the answer, so fetch the page before the agent states a number.

How we estimated the time saved: building and running your own search layer is roughly 8 to 16 hours for the request handling, the result parser and a page reader, plus 4 to 8 hours for the first month of upkeep as result pages change. That is 12 to 24 hours. The 1 minute is the install, key and first call once you already have a Monid key.

Free next step: run monid inspect -p tinyfish -e /search, then make one call on a question whose answer you already know and compare the first snippet with the page. Start at monid.ai.

FAQ

Is there a free web search API for AI agents?

Yes: through Monid, the TinyFish search endpoint is priced at $0.00 per call (Verified 2026-10-16), and its page fetch is free too. It returned 10 ranked results with snippets in our runs, with no search-vendor account.

How do I add web search to my AI agent?

Install the CLI, add a key, and give your agent https://monid.ai/SKILL.md. It learns to discover, inspect and run the search endpoint itself, then passes the URLs it wants to the fetch endpoint for page text.

How many phrasings should I run per question?

Three is a good start. Three phrasings of one question gave 18 unique URLs where any one gave 10, and only 4 URLs showed up in all three. Merge on URL and add phrasings until the union stops growing on your own questions.

Can I search Google with this?

These endpoints return their own indexes, not Google's page. For one-engine results, inspect the search endpoints in the web search category and choose one built to mirror that engine.

Why did my filtered search return nothing?

A search with domain_type set to news and a long recency_minutes returned an empty list with status COMPLETED and no error in our run. Retry without the filters, then add them back one at a time.

Published September 2026.

free web search apiweb search api for ai agentsweb search apisearch api for agentsai agents