Free Search for AI Agents

API & MCP

One free endpoint, two indexes. FreeSerp Main (index=sites, default, unchanged — main pages only): 20M+ homepage profiles with LLM summaries, Domain Rating and AI niche taxonomy, filterable and sortable on every field. FreeSerp Global (index=web): full-web search over 3.1B+ pages from our own engine — any URL, any language. No key, CORS-open, or wire it in as an MCP tool.

Quickstart

A single GET request. No authentication. By default you search FreeSerp Main — main pages only, 20M+ site profiles with LLM summaries (exactly the API you may already use):

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=ai+chatbot&ai_startups=1&sort=went_live&order=desc&size=3'

Add index=web to search the open web with FreeSerp Global — our own 3.1B+ page index. Results are ranked pages: url, title, snippet, language, publication date, and a site card (Domain Rating, category, live date) when we know the domain:

HTTP / cURL
curl 'https://freeserp.ai/api.php?index=web&q=how+to+fine-tune+llama+3&size=3'

Python

Python
import requests
# FreeSerp Main (default): newest AI startups with LLM summaries
r = requests.get('https://freeserp.ai/api.php', params={
    'q': 'ai chatbot', 'ai_startups': 1, 'sort': 'went_live', 'order': 'desc', 'size': 5,
})
for hit in r.json()['results']:
    print(hit['domain'], '—', hit['ai_summary'][:120])

# FreeSerp Global: any page on the web
r = requests.get('https://freeserp.ai/api.php', params={'index': 'web', 'q': 'how to fine-tune llama 3', 'lang': 'en', 'size': 5})
for hit in r.json()['results']:
    print(hit['url'], '—', hit['snippet'][:120])

JavaScript (fetch)

JavaScript
const r = await fetch('https://freeserp.ai/api.php?' + new URLSearchParams({
  index: 'web', q: 'best crm for small business', size: 5,
}));
const { results } = await r.json();
results.forEach(h => console.log(h.url, h.title, h.site?.dr));
Built for agents: results come pre-cleaned — no HTML to scrape, no pagination games.
Discover it live: GET /api.php?help=1 returns a machine-readable usage guide — every parameter, both indexes, recommended queries and caveats. Great as the first call an agent makes.

Two indexes

FreeSerp Global — index=webFreeSerp Main — index=sites (default)
WhatFull-web search: 3,132,469,027 pages from our own crawl (own extraction, own link graph), ranked by text relevance (title, headings, body, anchors), link authority and domain trust.Main pages only: homepage-level profiles of 20M+ live sites — LLM summary, Domain Rating, AI niche taxonomy, tech stack, live date. Every field filterable and sortable.
Unita page (any URL)a site (domain)
Paramsq (required), lang, fresh, published_from/to, ranking, size, fromq (optional), ai_startups, ai_categories, category, ai_source, dr_min/max, from_date/to_date, sort/order, content, all…
Resulturl, domain, title, snippet, language, published_at, crawled_at, score, site{dr, category, ai_categories, ai_source, went_live, summary}, source{index, captured_at, digest}domain, url, title, ai_summary, category, ai_categories, ai_source, dr, went_live, first_seen, tld, http_status…
Depthtop 100 candidates (from+size ≤ 100); total = size of that pool, not an exhaustive countexact total; from+size ≤ 10,000
Best forfacts, how-to, comparisons, grounding, any-language questionsdiscovering new sites & AI startups, competitor sets, domain lookups, niche browsing
Default: when index is omitted the request goes to FreeSerp Main — nothing changes for existing integrations. Pass index=web (alias global) to search the open web with FreeSerp Global (requires q). If FreeSerp Global is momentarily unavailable the request is served from FreeSerp Main with engine_fallback: true. On the search UI FreeSerp Global is the default tab.

Endpoint

GET https://freeserp.ai/api.php

Also reachable as /api. Read-only. Responses are cached ~30s at the edge.

Parameters

ParamTypeDefaultDescription
indexsites·websitesWhich index to search (see Two indexes). web = FreeSerp Global, full-web search, needs q (alias global); sites = FreeSerp Main (alias main). Param alias: mode.
qstring—web: full-text query over any page (title, headings, body, anchors). sites: title, AI summary and homepage text; exact domain names are boosted. Omit q to browse/filter the sites index.
langiso—web only. Language filter: en ru de fr es ja zh it pt pl nl tr cs vi ko ar uk sv id th… Alias: language.
fresh0·10web only. 1 ranks fresher pages higher (same as sort=fresh).
published_from / published_todate—web only. Publication-date window (YYYY-MM-DD).
rankingenumbm25_trustweb only, advanced. bm25_trust (text × domain trust), bm25 (text × link authority), bm25_rank, bm25_fresh.
sortenumrelevancesites: any sortable field (see Sorting); relevance = text score × Domain Rating. web: relevance or fresh.
orderasc·descdescsites. Sort direction (ignored for relevance).
sizeint20 · web 10Results per page, 1–100.
fromint0Offset for paging (sites: max 10,000; web: from+size ≤ 100).
FreeSerp Main parameters (index=sites, the default index):
all0·101 also returns parked/empty domains. Default: real content sites only.
ai0·101 restricts to AI-built sites (ai_source ∈ ai_likely, lovable, base44, v0, bolt).
ai_startups0·10Recommended for discovering real AI startups. Keeps only genuine AI-product niches (see field values) and strips the noise that category=ai lets through — AI-flavoured Shopify shops, directories and casinos.
helpany—Present ⇒ ignore the search and return a machine-readable usage guide (params, recommended queries, caveats, field list). ?help=1.
content0·101 also returns the full extracted page text of each result under content (not just the AI summary).
content_maxint—Cap the returned page text to N characters. Omit for the full text.
dr_min / dr_maxint—Domain Rating range filter (0–100).
from_date / to_datedate—Filter by went_live (YYYY-MM-DD).
Plus an exact-match filter for every keyword field — pass the field name as a query param:
categorykeyword—e.g. ai, betting/casino
ai_sourcekeyword—e.g. shopify, nextjs, lovable
ai_categorieskeyword—AI sub-niche, e.g. Image Generation
tldkeyword—e.g. ai, io
webserverkeyword—e.g. cloudflare, nginx
http_statusnumber—e.g. 200

Response

FreeSerp Global (index=web)

JSON
{
  "ok": true,
  "index": "web",
  "query": "how to fine-tune llama 3",
  "total": 97,                      // de-duplicated candidate pool (≤ 100), not an exhaustive count
  "count": 3, "from": 0, "size": 3,
  "sort": "relevance", "ranking": "bm25_trust",
  "filters": { "lang": "en" },
  "took_ms": 412, "engine_ms": 388, "cached": false,
  "results": [
    {
      "url": "https://example.com/blog/fine-tune-llama-3",
      "domain": "example.com",
      "title": "How to fine-tune Llama 3 on your own data",
      "snippet": "… step-by-step guide to fine-tune Llama 3 with LoRA on a single GPU …",
      "language": "en",
      "published_at": "2026-05-14", "crawled_at": "2026-07-12",
      "score": 341.2,
      "site": { "dr": 41, "category": "ai", "ai_categories": ["Code & Dev Tools"], "ai_source": "nextjs", "went_live": "2026-08-22", "summary": "Example is …" },
      "source": { "index": "FreeSerp Global", "captured_at": "2026-07-18T03:05:37Z", "digest": "sha1:…" }
    }
  ],
  "related_apis": { … }
}

site is null when the domain is not in FreeSerp Main. source.captured_at / source.digest identify the exact capture the page came from — reproducible evidence for grounding.

FreeSerp Main (index=sites)

JSON
{
  "ok": true,
  "index": "sites",
  "query": "ai chatbot",
  "total": 48213,
  "count": 3,
  "from": 0, "size": 3,
  "sort": "relevance", "order": "desc",
  "filters": { "real_site": "1" },
  "took_ms": 34, "engine_ms": 21,
  "results": [
    {
      "domain": "example.ai",
      "url": "https://example.ai",
      "title": "Example — AI chatbot for support",
      "ai_summary": "Example is an AI chatbot platform that …",
      "category": "ai",
      "ai_categories": ["AI Chatbot & Assistant"],
      "ai_source": "nextjs",
      "dr": 41, "went_live": "2026-08-22", "first_seen": "2026-07-10",
      "tld": "ai", "http_status": 200,
      "content_length": 8123, "html_size": 40213,
      "_score": 3182.4
    }
  ]
}

Sorting — every field

FreeSerp Global: sort=relevance (default) or sort=fresh. FreeSerp Main: pass any of these as sort=, with order=asc|desc:

relevancedomaincategoryai_categoriesai_sourcedrwent_livefirst_seenreal_sitetldhttp_statuscontent_lengthhtml_sizewebserveripfetched_at

All fields

FreeSerp Global results always carry: url domain title snippet language published_at crawled_at score site{…} source{index, captured_at, digest}.

Sites index — every field returned per result, and whether you can filter or sort on it:

FieldTypeSortFilterDescription
domain keyword ✓ ✓ Registered domain (e.g. example.com)
title text — ✓ Page <title>
ai_summary text — ✓ LLM-generated factual overview of the site
category keyword ✓ ✓ High-level category: 'ai', 'betting/casino', or null
ai_categories keyword ✓ ✓ AI sub-niche taxonomy (multi-valued)
ai_source keyword ✓ ✓ Builder / stack signal: wordpress, shopify, nextjs, lovable, v0, bolt, base44, ai_likely, not_ai…
dr number ✓ ✓ Domain Rating 0–100 (authority proxy)
went_live date ✓ ✓ Date the liveness probe first confirmed the site live
first_seen date ✓ ✓ Date the domain was first discovered
real_site number ✓ ✓ 1 = real content site, 0 = parked/empty/error
tld keyword ✓ ✓ Top-level domain (com, ai, io…)
http_status number ✓ ✓ Last HTTP status of the homepage
content_length number ✓ ✓ Extracted text length (bytes)
html_size number ✓ ✓ Raw HTML size (bytes)
webserver keyword ✓ ✓ Server header (nginx, Apache, cloudflare…)
ip ip ✓ ✓ Resolved IP address
fetched_at date ✓ — When the HTML was last fetched

Field values

The keyword fields you filter on take a fixed set of values. The most useful:

category

Broad heuristic bucket. ai betting/casino (null)  — ai is deliberately wide; prefer ai_startups=1 / ai_categories for real AI products.

ai_source — builder / tech stack

AI-builder signals: ai_likely lovable v0 bolt base44  · classic stacks: wordpress shopify wix webflow nextjs react not_ai

ai_categories — AI sub-niche (multi-valued)

Counted as a real AI startup by ai_startups=1:
AI Agents & Autonomous Code & Dev Tools AI Infrastructure & API AI Automation & Workflows LLM & Prompt Tools AI Search & Answers AI Website Builder No-code / App Builder Image Generation Video Generation Voice & Text-to-Speech Data & Analytics Research & Science Design & UI Chatbot & Assistant

Also present but treated as noise for startup discovery: E-commerce, Directory / Aggregator, Marketing & Ads, Sales & CRM, Lead Gen & Outreach, Finance & Trading, Healthcare & Medical, Education & Tutoring, Other AI, …

Not sure what exists? GET /api.php?help=1 and the MCP freeserp_list_endpoints tool both enumerate the live surface — never hard-code, ask the API.

Caveats — read this

Field / filterWhat it really means
total (web)FreeSerp Global returns the top 100 candidates after de-duplication; total is the size of that pool, not how many pages match on the whole web. Page inside the window with from/size.
published_at (web)The page's own publication date when it declares one (meta / schema / visible date). Missing for many pages — then use crawled_at, the date we fetched it.
freshness (web)FreeSerp Global is refreshed in batches from our own crawl; a page changed or created after its last capture (crawled_at) is not reflected yet. FreeSerp Main is refreshed daily.
engine_fallbackPresent and true when the web engine was unavailable and the response was served from the sites index instead.
went_liveThe date FreeSerp's liveness probe first confirmed the site reachable — not the startup's official launch date. A domain can be registered or launched well before we first see it live.
category=aiA broad keyword heuristic (AI phrases in the HTML). It also flags AI-flavoured Shopify shops, directories and casinos. For genuine AI products use ai_startups=1 and/or ai_categories.
ai_source=ai_likelyA heuristic "looks AI-built" signal — useful but noisy on its own. Combine with ai_categories for precision.
drDomain Rating 0–100 from our own web-graph (Ahrefs-calibrated), not a live third-party API. Brand-new domains may still read dr: null until scored.
first_seenWhen the domain entered our discovery feed (often its NRD registration date), not when it went live.

Data & coverage

FreeSerp Global: 3,132,469,027 pages, built and ranked by us — own crawl, own extraction, own link graph for authority and domain trust. Languages: en 1,256M, ru 228M, de 187M, fr 162M, ja 160M, es 158M, zh 140M, it, pt, pl, nl, tr, cs, vi and more. Every result is reproducible down to the capture (source.captured_at, source.digest).

FreeSerp Main (main pages only): ~20M live sites from our own continuously-refreshed discovery pipeline (newly-registered domains are probed daily; live ones are crawled, LLM-summarised, categorised and DR-scored). Global — every TLD and language. Each record is the homepage: title, extracted text, ai_summary, tech stack, DR and live date. It is a discovery index of what is newly live on the web — not a crawl of every page of every site (that is what FreeSerp Global is for).

Limits, paging & errors

Rate limits

No hard limit and no key — the service is free and open. Please be reasonable (a few requests/second), cache when you can, and identify yourself so we can reach you before a change or ask you to ease off instead of blocking. Responses are edge-cached ~30s.

Paging

Web: from + size ≤ 100 — the engine returns the top-100 candidates for a query; refine the query or add lang/published_from instead of paging deeper. Sites: size ≤ 100 per page; from + size ≤ 10,000. To pull a large set, narrow with filters (date range, ai_categories, dr_min) rather than paging to the cap.

Errors

HTTP 200 with "ok": true on success. On failure you get a non-2xx with an error body:

JSON
{ "ok": false, "error": "upstream", "detail": "search_phase_execution_exception" }
StatusMeaning
200OK — results (may be empty; check total).
204CORS pre-flight (OPTIONS).
400query_required — index=web needs q; use index=sites to browse without a query.
502Upstream search error — retry with backoff (web-engine outages are normally masked by engine_fallback).

Bad params never error — unknown filters are ignored and an invalid sort falls back to relevance, so a query always returns something. The echoed filters object shows exactly what was applied.

Statistics

A live snapshot of the whole index, refreshed every 30 minutes — no heavy query on your side.

GET https://freeserp.ai/api.php?stats=1
JSON
{
  "ok": true,
  "generated_at": "2026-09-06T10:16:35+00:00",
  "web_index": { "name": "FreeSerp Global", "pages": 3132469027, "nodes": 18, "languages": { "en": 1256209788, "ru": 228281221, … }, "engine_ready": true },
  "totals":  { "real_sites": 16273795, "all_sites": 21086714 },
  "new":     { "today": 29247, "yesterday": 31800, "last_7d": 232787, "last_30d": 11289030 },
  "ai_startups": { "total": 33429, "today": 72 },
  "by_category": [ {"key":"ai","count":78674}, {"key":"betting/casino","count":806182} ],
  "top_ai_categories": [ {"key":"AI Agents & Autonomous","count":10467}, … ],
  "top_ai_source": [ … ], "top_tld": [ … ],
  "dr": { "avg": 8.4, "min": 0, "max": 99, "histogram": [ … ] },
  "by_day": [ {"key":"2026-09-06","count":29247}, … ],
  "gambling": { "today": {"original":…,"affiliate":…}, "total": {…} },
  "pipeline": { "summary_todo": …, "went_live_today": …, "probe_due": … }
}

Over MCP, the same snapshot is the freeserp_stats tool. The robot also keeps 30 days of half-hourly history in freeserp_stats for trend charts.

Examples & recipes

★ Answer a question from the web (index=web)

HTTP / cURL
curl 'https://freeserp.ai/api.php?index=web&q=how+does+chatgpt+search+choose+sources&size=5'

English results, fresher pages first

HTTP / cURL
curl 'https://freeserp.ai/api.php?index=web&q=best+link+indexing+services&lang=en&fresh=1'

Pages published this year only

HTTP / cURL
curl 'https://freeserp.ai/api.php?index=web&q=gpt-5+pricing&published_from=2026-01-01&size=10'

Grounding for an agent: ask, then read the site card

Python
r = requests.get('https://freeserp.ai/api.php', params={'index': 'web', 'q': 'best backlink indexing service', 'size': 8}).json()
for h in r['results']:
    site = h['site'] or {}
    print(h['url'], '| DR', site.get('dr'), '|', site.get('summary', '')[:80])

★ Discover new AI startups in a niche (default index — recommended combo)

HTTP / cURL
curl 'https://freeserp.ai/api.php?ai_startups=1&ai_categories=AI%20Agents%20%26%20Autonomous&from_date=2026-09-01&sort=went_live&order=desc'

Newest AI sites, most authoritative first

HTTP / cURL
curl 'https://freeserp.ai/api.php?ai=1&sort=dr&order=desc&size=10'

All sites built on Shopify, most authoritative first

HTTP / cURL
curl 'https://freeserp.ai/api.php?ai_source=shopify&sort=dr&order=desc&size=25'

High-DR news sites that went live in the last two weeks

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=news&dr_min=30&from_date=2026-08-16&sort=went_live&order=desc'

Browse by niche, no text query

HTTP / cURL
curl 'https://freeserp.ai/api.php?ai_categories=Image%20Generation&sort=dr&order=desc'

Return full page text, not just the summary

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=ai+chatbot&content=1&content_max=4000&size=3'

Look up one exact domain (record, DR, stack, summary)

Pass the full domain (any TLD) as q — it is boosted to the top; take the first result and confirm results[0].domain matches. Add all=1 so parked/empty domains still resolve.

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=mynewstartup.ai&all=1&size=1'
Scope: FreeSerp Main is a discovery index of recently-live / newly-registered domains — long-established sites (e.g. google.com) may not be in it. If results[0].domain ≠ your query, the domain isn't in that index; the web index still has its pages.

Is this a real site or parked/dead?

Check real_site and http_status on the returned record (1 = real content, 0 = parked/empty/error).

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=somedomain.io&all=1&size=1'

Find competitors / similar sites in a space

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=vector+database&ai_startups=1&dr_min=10&sort=dr&order=desc&size=25'
Tip for agents: to enumerate a whole niche, don't page to the cap — loop by from_date/to_date week-windows with a fixed ai_categories filter, or tighten with dr_min.

Identify yourself (optional)

There is no key and no signup — which also means that when something is about to change, we have no way to reach you. These four fields fix that. Every one is optional, nothing is validated, and none of them affect your results.

HTTP / cURL
curl 'https://freeserp.ai/api.php?q=ai&agent=MyAgent/1.0&[email protected]&project=Acme&website=https://acme.com'
FieldExamplePurpose
agentMyAgent/1.0Your agent name + version (also accepted as the X-Agent header).
email[email protected]Contact address — contact= works the same. Used only to reach a human about this API.
projectAcme ResearchThe project/product making the calls.
websitehttps://acme.comProject website.

Over MCP, pass the same fields as arguments to any freeserp_search call. Sending them once is enough. What it buys you: we can warn before a breaking change, ask what you are missing, and — if your traffic starts hurting the service — ask you to slow down instead of blocking you. Stored privately next to request counts; never published, never shared.

What we will never ask for: no key, no token, no account. If a page on this site ever asks you to register to make a request, it is not this site.

MCP connector

FreeSerp ships a hosted Streamable-HTTP MCP server — one URL, no install. Tools and their schemas are generated live from the field registry, so they never drift from the API.

MCP https://freeserp.ai/mcp

A plain GET on that URL returns the live tool catalog (server, transport, tool_count, and every tool with its description) — same shape your client discovers over JSON-RPC:

HTTP / cURL
curl 'https://freeserp.ai/mcp'

Add it to Claude (Desktop / Code / any MCP client)

Point the client at the remote endpoint via mcp-remote:

JSON
{
  "mcpServers": {
    "freeserp": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://freeserp.ai/mcp"]
    }
  }
}

Restart the client — your agent now has these tools:

ToolWhat it does
freeserp_searchThe main search over both indexes. Default index: "sites" (FreeSerp Main) with ai_startups, ai_categories, sort, filters…; index: "web" with q, lang, fresh, published_from/to for the open web (FreeSerp Global).
freeserp_helpUsage guide: quickstart, every param, recommended AI-startup query, caveats. Call this first.
freeserp_statsLive index statistics — totals, new today/7d, AI-startup counts, top niches/TLDs, DR distribution (refreshed every 30 min).
freeserp_list_endpointsField catalog — every field with type and whether it is sortable/filterable.
freeserp_getEscape hatch: raw GET of the REST API with any query string.
Tip: have the agent call freeserp_help (or freeserp_list_endpoints) first — it learns every field and the recommended ai_startups combo, so it composes precise queries on its own instead of guessing.

Raw JSON-RPC

Talk to it directly — initialize, then tools/list / tools/call:

JSON
# discover tools
curl -s 'https://freeserp.ai/mcp' -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# run a search
curl -s 'https://freeserp.ai/mcp' -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
        "name":"freeserp_search",
        "arguments":{"q":"ai chatbot","ai_startups":true,"sort":"went_live","size":5}}}'

# FreeSerp Global: any page on the web
curl -s 'https://freeserp.ai/mcp' -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
        "name":"freeserp_search",
        "arguments":{"index":"web","q":"how to fine-tune llama 3","lang":"en","size":5}}}'
Prefer plain HTTP? The REST endpoint above is the same backend — point any framework (LangChain, LlamaIndex, a raw tool-call) at /api.php and skip MCP entirely.