How do I migrate from Tavily to another search API?

Point Tavily code at Grounder's Tavily-shaped endpoint by changing the URL and sending a scoped OAuth access token; 8 request fields work, Extract, Crawl and answers do not.

Last checked

To move Tavily code to Grounder (grounder.net), change https://api.tavily.com/search to https://api.grounder.net/compat/tavily/search and send a search-scoped OAuth access token. Existing legacy search keys still work.

Last checked: 20 October 2026. Disclosure: Grounder (grounder.net) publishes this page, and Tavily is one of the 10 search providers Grounder routes searches to.

What changes

TavilyGrounder's Tavily-shaped endpoint
URLPOST https://api.tavily.com/searchPOST https://api.grounder.net/compat/tavily/search
AuthorizationAuthorization: Bearer with a Tavily keyAuthorization: Bearer with a Grounder OAuth access token scoped to search; an existing legacy key also works, including in Tavily's api_key body field
Rate limit100 requests a minute (development keys), 1,000 (production keys)120 requests a minute per key
max_results0 to 20, default 101 to 100, default 5
Cost$0.008 per credit pay as you go (basic search 1 credit, advanced 2); 1,000 free credits a monthFirst 1,000 searches free per account in total, up to 100 a day
Other endpointsExtract, Crawl, Map, ResearchNot available

Request fields:

Tavily fieldOn GrounderNote
queryHonoredRequired
max_resultsHonoredSet it explicitly: the default is 5, and 0 is not accepted
daysHonoredRolling window in days, any topic; Tavily's current API reference lists time_range instead, so convert (for example year becomes days: 365)
start_date, end_dateHonoredUsed when days is absent
include_domains, exclude_domainsHonoredOnly one applies; include wins
include_raw_contentHonoredraw_content is the result's passage text, not the full page
include_answerAccepted, ignoredanswer is always an empty string
include_imagesAccepted, ignoredimages is always an empty list
search_depth, topic, chunks_per_source, include_usageAccepted, ignored
time_range, country, language, exact_match, safe_search and any other fieldNot supportedIgnored

The response keeps Tavily's keys: query, follow_up_questions (null), answer, images, results, response_time (seconds) and request_id. Each result has id (canonical URL), title, url, content, score, published_date (null when unknown) and raw_content (null unless requested), plus a grounder object with provider, found_by, licensed, rank and, for licensed results, publisher_name. No usage field is listed. As in the native API, score is the finding provider's own and is not comparable across providers; use grounder.rank for order.

Results are merged and deduplicated across providers. Licensed sources only is on by default for signed-up accounts, so a call can return fewer results than max_results.

Steps

1. Authorize HTTP

Read https://api.grounder.net/.well-known/oauth-protected-resource/v1/search, register a public OAuth client, then sign in and request scope=search for resource https://api.grounder.net/v1/search. Store the returned access token as GROUNDER_ACCESS_TOKEN and refresh it before it expires. The API docs describe the flow. Existing legacy search keys still work.

2. Change the URL and access token

Diff
- https://api.tavily.com/search
+ https://api.grounder.net/compat/tavily/search

Before:

Shell
curl https://api.tavily.com/search \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "what is the half-life of caffeine", "max_results": 5, "include_domains": ["nih.gov"], "time_range": "year"}'

After:

Shell
curl https://api.grounder.net/compat/tavily/search \
  -H "Authorization: Bearer $GROUNDER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "what is the half-life of caffeine", "max_results": 5, "include_domains": ["nih.gov"], "days": 365}'

3. Update your code

Python:

Python
import os

import requests

resp = requests.post(
    "https://api.grounder.net/compat/tavily/search",
    headers={"Authorization": f"Bearer {os.environ['GROUNDER_ACCESS_TOKEN']}"},
    json={
        "query": "what is the half-life of caffeine",
        "max_results": 5,
        "include_domains": ["nih.gov"],
        "days": 365,
    },
    timeout=30,
)
resp.raise_for_status()
for r in resp.json()["results"]:
    print(r["url"], r["grounder"]["provider"], r["grounder"]["licensed"])

TypeScript (Node 18 or later, as an ES module):

TypeScript
const res = await fetch("https://api.grounder.net/compat/tavily/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GROUNDER_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "what is the half-life of caffeine",
    max_results: 5,
    include_domains: ["nih.gov"],
    days: 365,
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
for (const r of data.results) console.log(r.url, r.grounder.provider, r.grounder.licensed);

With the official tavily-python SDK (version 0.8.5, released 6 October 2026), pass the current OAuth access token as api_key and api_base_url="https://api.grounder.net/compat/tavily" to TavilyClient; the client appends /search and sends it as a Bearer header. Refresh the token outside that client before it expires. Grounder's notes say the endpoint's response was parsed by the unmodified SDK without error (undated), so test it on your own code in step 5.

4. Keep Tavily's results

By default Grounder sends each call to the provider, or pair of providers, most likely to answer it well. To keep Tavily, set Tavily to Always and Licensing to Any source on the account page, under Routing. To have Tavily bill you directly, add your own Tavily key in the same table. To pin one search, call the native endpoint, which returns Grounder's own response shape:

Shell
curl https://api.grounder.net/v1/search \
  -H "Authorization: Bearer $GROUNDER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "what is the half-life of caffeine", "top_k": 5, "requested_provider": "tavily", "routing_settings": {"licensed_only": false}}'

5. Verify

Send 10 to 20 real queries to both APIs and compare result counts and URLs. Check grounder.provider and grounder.licensed on each result; fewer results than expected usually means Licensed sources only is on. Each call is a recorded search and counts toward the 1,000 free ones. curl https://api.grounder.net/v1/providers needs no key and lists the 10 providers.

6. Use MCP instead

Add https://api.grounder.net/mcp to your MCP client and sign in with Google, GitHub or Apple. The search tool takes query, top_k, domains, days, include_text and requested_provider; steps are in Docs.

What Tavily credits cost

Tavily's search credits, from its pricing and API reference pages: basic, fast and ultra-fast depths cost 1 credit and advanced costs 2. Pay as you go is $0.008 per credit, so a basic search is $8 per 1,000 and an advanced one $16 per 1,000; the Project plan ($30 a month for 4,000 credits) works out to $0.0075 per credit. Credits reset on the first day of each calendar month.

OptionPrice per 1,000 searchesFree tier
Tavily$8 (basic); $16 (advanced)1,000 credits a month
Exa$7 (auto); $4 (lite)$10 credit a month
Brave Search API$5$5 credit a month
Perplexity Search API$5; $1 (fast search)Not published
GrounderFirst 1,000 searches freeUp to 100 a day, 120 a minute

If you move to another API directly

TavilyBraveExaPerplexity
queryqqueryquery
max_results (0 to 20, default 10)count (maximum 20, default 20)numResults (1 to 100, default 10)max_results (1 to 20, default 10)
search_depth (basic, advanced, fast, ultra-fast)No equivalent; LLM Context is a separate endpointtype (auto, lite, deep-lite, deep)search_type set to fast
include_domains (300), exclude_domains (150)site: and -site: inside qincludeDomains, excludeDomains (1,200 each)search_domain_filter (20 domains, allow or deny)
time_range: day, week, month, yearfreshness: pd, pw, pm, pystartPublishedDate, endPublishedDatesearch_recency_filter: hour, day, week, month, year
start_date, end_datefreshness as YYYY-MM-DDtoYYYY-MM-DDstartPublishedDate, endPublishedDatesearch_after_date_filter, search_before_date_filter (M/D/YYYY)
country (a country name, topic general only)country (2-character code)userLocationcountry (ISO 3166-1 alpha-2)
language, filter_by_languagesearch_langNo request field foundsearch_language_filter (10 codes)
include_raw_contentLLM Context endpoint (extracted chunks)contents.textmax_tokens_per_page caps the page text in snippet
include_answerAnswers plan ($4 per 1,000 plus tokens)Answer endpoint ($5 per 1,000)Agent API (Sonar chat completions ended 27 September 2026)
ExtractNoneContents API ($1 per 1,000 pages)fetch_url tool in the Agent API
results[].contentweb.results[].descriptionresults[].highlights or textresults[].snippet

Side by side, in more depth: Tavily vs Exa, Tavily vs Brave and Tavily alternatives.

Where Grounder fits

Grounder is a web search API and MCP server for AI agents: one search goes across 10 web search providers, results are deduplicated, and each is marked with its provider and whether it is licensed. It returns sources, not an answer. Grounder's benchmark, run by Grounder, searched 887 questions (table as of 20 October 2026 05:22 UTC):

RowSimpleQA correct given attempted (671 questions)SealQA correct given attempted (216 questions)
Grounder optimized14.3%12.1%
Grounder optimized, all sources97.9%36.6%
Perplexity96.1%36.8%
Exa88.6%32.1%
Tavily86.6%24.5%
Brave85.2%16.4%

Each provider's row is its default search. Figures are correct given attempted: the share of the questions a search answered that it got right, with a "don't know" counted as not attempted. Grounder optimized answers only from licensed sources, so it gets fewer answers right than the all-sources row, which searches every source. Grounder optimized is what a signed-up account gets by default; the all-sources row is the same routing with nothing filtered out. Both Grounder rows are routed as Grounder routes on 19 October 2026, and that routing was tuned on these same searches. Read against Tavily: the all-sources row is ahead of Tavily on both benchmarks, but the default row (14.3% and 12.1%) is far behind it. Each question was searched once on every provider's default search (top 10 results, 60 seconds), answered by Z.ai's GLM-5.3-Flash and graded with OpenAI's SimpleQA grader, from 8 to 13 October 2026. Full method: /benchmarks. For a wider comparison, see the best search API for AI agents.

FAQ

Is there a drop-in Tavily-compatible endpoint?

Yes: POST https://api.grounder.net/compat/tavily/search takes Tavily's request shape and returns Tavily's response shape plus a grounder object on each result. It accepts an OAuth access token with the search scope; existing legacy search keys still work.

Does it support search_depth, include_answer, Extract or Crawl?

No. search_depth and include_answer are accepted and ignored, and answer is always empty. Extract, Crawl, Map and Research are not available.

Do I need a new key?

No. Register a public OAuth client, sign in, request the search scope for https://api.grounder.net/v1/search and send the returned access token. Existing legacy search keys still work.

How does billing change from Tavily's credits?

Tavily charges credits: $0.008 each on pay as you go, 1 for a basic search and 2 for an advanced one, so $8 and $16 per 1,000 searches. Grounder's first 1,000 searches are free, up to 100 a day, and a search counts once however many providers it reaches.

Which fields map if I move from Tavily to Exa, Brave or Perplexity instead?

The core fields map directly: query becomes q (Brave) or stays query (Exa, Perplexity); max_results becomes count (Brave, maximum 20), numResults (Exa, up to 100) or max_results (Perplexity, 1 to 20); include_domains and exclude_domains become site: operators (Brave), includeDomains and excludeDomains (Exa) or search_domain_filter (Perplexity, 20 domains). The table in this guide lists the rest.

Next step

Your first 1,000 searches are free, up to 100 a day. No card needed. Connect an MCP client to https://api.grounder.net/mcp, or read the HTTP API docs to use OAuth.

Sources

  1. https://grounder.net/docs (20 October 2026)
  2. https://docs.tavily.com/documentation/api-reference/endpoint/search (20 October 2026)
  3. https://docs.tavily.com/documentation/api-credits (20 October 2026)
  4. https://docs.tavily.com/documentation/rate-limits (20 October 2026)
  5. https://www.tavily.com/pricing (20 October 2026)
  6. https://pypi.org/project/tavily-python/ and https://github.com/tavily-ai/tavily-python/blob/master/tavily/tavily.py (20 October 2026)
  7. https://api-dashboard.search.brave.com/app/documentation/web-search/query and https://brave.com/search/api/ (20 October 2026)
  8. https://exa.ai/pricing and https://exa.ai/docs/reference/search (20 October 2026)
  9. https://docs.perplexity.ai/docs/search/quickstart , https://docs.perplexity.ai/docs/search/filters/date-time-filters and https://docs.perplexity.ai/docs/getting-started/pricing (20 October 2026)
  10. https://grounder.net/benchmarks and https://api.grounder.net/v1/demo/results (20 October 2026, as of 05:22 UTC)
  11. https://grounder.net/pricing (20 October 2026)
  12. https://arxiv.org/abs/2411.04368 and https://arxiv.org/abs/2506.01062 (20 October 2026)