Exa-style vs Tavily-style search requests, side by side
Exa and Tavily name the same ideas differently. An Exa-style search takes numResults and a contents object and returns results with text, highlights and publishedDate. A Tavily-style search takes max_results and include_raw_content and returns content, raw_content and an optional answer. ContextFetch accepts both, at /v1/search and /tavily/search, so you can keep whichever SDK you already use. This guide sends one query both ways and maps the fields.
1. The request fields
- The query is
queryin both. - The number of results is
numResultsin Exa style andmax_resultsin Tavily style. - Domain filters are
includeDomainsandexcludeDomainsin Exa style,include_domainsandexclude_domainsin Tavily style. - The full page as Markdown is
contents.textin Exa style andinclude_raw_contentin Tavily style. - A date cutoff is
startPublishedDatein Exa style. For a date cutoff, use the Exa-style route. - A quoted direct answer is
include_answerin Tavily style; in Exa style it is a separate call to/v1/answer.
/v1/search accepts camelCase and snake_case, so num_results works there too, which matters because Exa's Python and TypeScript SDKs send different styles.
2. The response fields
An Exa-style response has results, each with id, url, title, score and publishedDate, plus text, highlights, highlightScores and prunedContext when you request them in contents. It also reports costDollars.
A Tavily-style response has query, results with title, url, content, raw_content and score, an answer when you ask for one, and response_time. content is the passage of the page most relevant to the query.
3. Which one to use
Use the format your code already speaks: both routes run the same search pipeline and cost one credit per search. If you are starting fresh, the Exa-style route gives you more to work with: publication dates and a date cutoff, scored highlights, pruned context, and /v1/findSimilar for pages like a given URL. Choose the Tavily style when your stack is built around tavily-python or @tavily/core.
To move existing code over, see the Tavily migration guide.
The complete code
Python, runnable as is with CONTEXTFETCH_API_KEY set. We ran it against the live API; the output below is what it printed.
import jsonimport osimport urllib.request API = "https://api.contextfetch.dev"KEY = os.environ["CONTEXTFETCH_API_KEY"] def post(path, body): req = urllib.request.Request( API + path, data=json.dumps(body).encode(), headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=90) as resp: return json.load(resp) query = "how does HNSW indexing work" exa = post("/v1/search", { "query": query, "numResults": 3, "contents": {"highlights": True},})tavily = post("/tavily/search", { "query": query, "max_results": 3, "include_answer": True,}) print("Exa style, fields of a result: ", sorted(exa["results"][0]))print("Tavily style, fields of a result:", sorted(tavily["results"][0]))print("Tavily style, top-level fields: ", sorted(tavily)) print("\nExa style results:")for r in exa["results"]: print(f" {r['score']:.2f} {r.get('publishedDate') or 'no date'} {r['url']}")print("Tavily style results:")for r in tavily["results"]: print(f" {r['score']:.2f} {r['url']}") Exa style, fields of a result: ['highlightScores', 'highlights', 'id', 'prunedContext', 'publishedDate', 'score', 'text', 'textSource', 'title', 'url']
Tavily style, fields of a result: ['content', 'raw_content', 'score', 'title', 'url']
Tavily style, top-level fields: ['answer', 'images', 'query', 'request_id', 'response_time', 'results']
Exa style results:
1.00 no date https://ai-tldr.dev/learn/embeddings-vector-databases/similarity-search-indexing/hnsw-explained/
1.00 no date https://milvus.io/docs/hnsw.md
0.99 no date https://www.techplained.com/vector-databases
Tavily style results:
1.00 https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes
1.00 https://ai-tldr.dev/learn/embeddings-vector-databases/similarity-search-indexing/hnsw-explained
1.00 https://qdrant.tech/course/essentials/day-2/what-is-hnswThe same call with curl
The raw HTTP request, and the response it returned (long text fields and lists shortened).
curl -s https://api.contextfetch.dev/v1/search \ -H "Authorization: Bearer $CONTEXTFETCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "how does HNSW indexing work", "numResults": 2, "contents": {"highlights": true}}'{
"requestId": "3a5b90af35394d5f8f1e57ac16f23984",
"results": [
{
"id": "26579996-9a8b-59e9-ab94-ee0b893f6041",
"url": "https://milvus.io/docs/hnsw.md",
"title": "HNSW | Milvus Documentation",
"score": 0.9991766856964429,
"publishedDate": null,
"text": null,
"highlights": [
"# HNSW\n\nThe **HNSW** index is a **graph-based** indexing algorithm that can improve performance when searching for high-dimensional floating vectors. It offers **excellent** search accuracy and **low** latency, while it requires **high** memory overhead to maintain its hierarchic…",
"A higher `efConstruction` generally results in a better quality graph but requires more time to build.\n- `ef`: The number of neighbors evaluated during a search. Increasing `ef` improves the likelihood of finding the nearest neighbors but slows down the search process.\n\nFor detai…",
"| Parameter | Description | Value Range | Tuning Suggestion |\n| --- | --- | --- | --- |\n| `M` | Maximum number of connections (or edges) each node can have in the graph, including both outgoing and incoming edges. This parameter directly affects both index construction and search…"
],
"highlightScores": [
0.9991766856964429,
0.9930426086304425,
0.9092805029177297
],
"prunedContext": "# HNSW\n\nThe **HNSW** index is a **graph-based** indexing algorithm that can improve performance when searching for high-dimensional floating vectors. It offers **excellent** search accuracy and **low** latency, while it requires **high** memory overhead to maintain its hierarchic…",
"textSource": "page"
},
{
"id": "5f939eb4-d29e-540f-a088-9ee2f20eff4c",
"url": "https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world",
"title": "Hierarchical navigable small world",
"score": 0.9985867225653056,
"publishedDate": "2024-02-22",
"text": null,
"highlights": [
"# Hierarchical navigable small world\n\nAlso known as: Hierarchical Navigable Small World graphs, HNSW indexes, HNSW\n\nHierarchical navigable small world (HNSW) is an algorithm for approximate nearest neighbor search. It is used to find items that are similar to a query item in a la…",
"In a small-world graph, most nodes can be reached from other nodes through a short chain of links.\n\nIn a navigable graph, a search procedure can use local information to move toward a target. Jon Kleinberg's work on navigation in small-world networks is an important example of th…",
"Worst-case performance of popular approximate nearest neighbor search implementations: Guarantees and limitations.\n\nThirty-seventh Conference on Neural Information Processing Systems. arXiv:2310.19126. nmslib/hnswlib, nmslib, 2024-03-18, retrieved 2024-03-19 \"Chroma Documentation…"
],
"highlightScores": [
0.9985867225653056,
0.9612213818149088,
0.004651995836965128
],
"prunedContext": "# Hierarchical navigable small world\n\nAlso known as: Hierarchical Navigable Small World graphs, HNSW indexes, HNSW\n\nHierarchical navigable small world (HNSW) is an algorithm for approximate nearest neighbor search. It is used to find items that are similar to a query item in a la…",
"textSource": "page"
}
],
"costDollars": {
"total": 0.001
},
"searchTimeMs": 178,
"searchTime": 178,
"contextfetch": {
"tokens": {
"raw": 4057,
"pruned": 912,
"savedPct": 77.52033522307123
},
"sources": {
"local": 2
},
"cache": "semantic",
"timingsMs": {
"recall": 0,
"fetch": 0,
"rerank": 157,
"total": 178
}
}
}