Gologin
← Blog

Exa AI Review 2026: Search Quality, Formats and Pricing for AI Agents

Most search APIs were built for people and adapted for agents. Exa was built the other way around.

It doesn’t rank pages by keywords. It ranks them by meaning, using embeddings-based retrieval, and it hands back page content an LLM can read without a scraping layer in between.

If you’re:

  • building AI agents,
  • running a RAG pipeline,
  • or choosing a web search API for LLMs,

this Exa AI review is for you. I ran the same 10 agent-style queries through every major Exa search mode on October 13–14, 2026, measured latency and cost per call, tested every content format, and pointed the contents endpoint at pages behind logins.

Here’s what held up, and what didn’t.

TL;DR and Fact Sheet

The short version of this Exa AI review: Exa answered faster than Tavily in my tests and was more consistent at surfacing primary sources. Instant search came back in under a second at $4 per 1,000 calls, and it favoured official docs and original announcements over news coverage. The trade-offs: publish dates on only about half the results, cached pages that can be months old unless you force a fresh crawl, and no access to anything behind a login.

Exa (October 2026)
What it is Neural (semantic) search API + page contents for LLMs
Core endpoints Search, Contents, Answer, Agent, Monitors
Search modes instant, fast, auto, deep-lite, deep, deep-reasoning
Output JSON with full text, highlights, AI summaries or schema-based structured data
Pricing model Pay as you go, no subscription
Search price $4 (instant) to $15 (deep-reasoning) per 1,000 requests
Free usage $10 in credits every month, no card
MCP Hosted at mcp.exa.ai, listed in Claude’s connector directory
Websets Separate product, from $49/month
Logged-in pages Not supported

What Is Exa and Who Is It For?

Exa is a neural search API (or semantic search API): it embeds your query and finds pages whose meaning is closest to it, so you describe the page you want instead of guessing its keywords.

exa ai

The Exa search API returns structured JSON with titles, URLs, dates and, optionally, each page’s content. A contents endpoint fetches clean text for any list of URLs. This Exa review covers both, plus the answer endpoint and the MCP server.

Exa fits three groups well:

  • Agent builders who need low-latency search inside a tool loop, where every second compounds.
  • RAG teams that want canonical sources (official docs, original filings, primary announcements) rather than articles about them.
  • MCP users who want real-time web data for AI agents in Claude, Cursor or any MCP client.

Getting started takes two minutes: create an Exa API key in the dashboard, and the Exa API docs include copy-paste examples for Python and JavaScript.

What it doesn’t do is sign in anywhere.

Testing Methodology

For this Exa AI review, every number comes from a Python harness calling the REST API and logging Exa’s own costDollars field.

Queries. The same 10 prompts I used for the Tavily review, so the results are directly comparable:

  • 4 freshness queries (a model release, a Fed rate decision, a Python release, AI agent funding rounds), sent with category: news
  • 4 relevance queries (Tavily in LangChain, BM25 vs dense retrieval, Playwright connect_over_cdp, MCP transports)
  • 2 niche queries (aiohttp rate limiting, pgvector HNSW tuning)

Modes. Every query ran on instant, fast and auto with numResults=5 and full text. The four news queries also ran on deep.

Extra tests. Five content formats on one query, cached vs live contents on three URLs, the contents endpoint against 8 login-gated and protected pages, plus /findSimilar and /answer.

Spend. 74 API requests (53 search, 19 contents, 1 answer, 1 find similar) for $0.39 in Exa credits, all inside the free monthly $10, with a 100% success rate.

Exa API usage dashboard after the benchmark: 74 requests across Search, Contents, Answer and Find similar, 100% success rate

Benchmark Results: Formats, Latency and MCP

Latency and cost by search mode

Mode Latency p50, news queries Latency p50, other queries Results with a date Cost per query
instant 0.80s 0.83s 54% $0.004
fast 0.90s 0.80s 50% $0.007
auto 0.92s 6.62s* 54% $0.007
deep 10.1s not tested 55% $0.012

*Auto latency on non-news queries was 1.96s p50 on October 13 and 6.6s on October 14, with server time pinned at almost exactly 6.05s on every query. Same queries, same code. Treat auto latency as variable and use fast when you need a hard budget.

The headline: instant and fast are genuinely sub-second. That’s 2–5x faster than the Tavily numbers from my previous test (2.24s basic, 4.40s advanced). In an agent that searches five times per task, that difference is the whole user experience.

Deep search, at 10 seconds and $0.012 per call, belongs in research steps, not tight loops.

Search relevance and freshness

Exa’s strongest result is source quality: openai.com for the model release, federalreserve.gov for the rate decision, docs.python.org for Python, the official LangChain docs for the integration. Tavily returned mostly news outlets and blogs. On news queries, every mode found a same-day or previous-day result on three of four topics.

The weakness is metadata. Only about half of results carried a publishedDate (88% on Tavily), and some were crawl timestamps: a Fed release from October 7 came back dated October 13.

Output formats

Format What came back (MCP spec page) Extra cost
text 13,002 chars of Markdown-style text none on the estimate
text + includeHtmlTags 22,595 chars with HTML tags kept none on the estimate
highlights (with a query) 607 chars, the relevant passage only none on the estimate
summary 458-char AI summary +$0.003 for 3 pages
summary + JSON schema {“spec_version”:”2025-03-26″,”transports”:[“stdio”,”Streamable HTTP”]} +$0.003 for 3 pages

Highlights and summaries cut tokens 20–200x versus full text, which matters more than any price difference. Structured data extraction via a JSON schema returns parseable JSON out of the box. There’s no true raw HTML: includeHtmlTags keeps tags inside extracted text, not the original source.

Note the spec_version: 2025-03-26. The cached copy still labelled it “Latest”, although newer specs exist.

Get contents and livecrawl

Contents come from cache by default. Forcing a fresh fetch with maxAgeHours: 0 (which replaced the deprecated livecrawl flag) took 1.33s for three URLs versus 0.61s cached. For docs, prices and specs, pay the extra 0.7 seconds.

Exa request log for a cached /contents call: 23 ms, $0.001, source cached

Find similar links

/findSimilar returned five related pages for Tavily’s docs in 0.84s ($0.004), but the response now carries a Deprecation: true header. For new builds, describe the source page in a regular search instead.

Exa MCP: Availability and Tools

The Exa Model Context Protocol (MCP) server runs hosted at https://mcp.exa.ai/mcp or locally via npx -y exa-mcp-server. In Claude’s connector directory you’ll see web_search_exa and get_code_context_exa, which searches GitHub repos, docs sites and Stack Overflow for coding context. The docs also list web_search_exa, web_fetch_exa and agent_run as the defaults for direct MCP setups.

Exa MCP connector in Claude's connector directory, with web_search_exa and get_code_context_exa tools

Exa API Pricing Deep Dive

Exa pricing, as listed on the exa.ai pricing page, is pay as you go. There’s no subscription and no minimum, and every account gets $10 in free credits that reset monthly.

Endpoint Price per 1,000 Notes
Search: instant $4 Up to 10 results included
Search: fast / auto $7 Up to 10 results included
Search: deep-lite / deep $12 Listed in the Deep Search table of the pricing page
Search: deep-reasoning $15 Replaced /research in April 2026
Contents (text, highlights or summary) $1 per 1,000 pages, per type A page with text + highlights counts twice
Answer $5 LLM answer with citations
Extra results above 10 $1 per 1,000 results Standard and deep search

In my tests, a 5-result search with full text was estimated at the flat search price ($0.004 instant, $0.007 auto); summaries and contents-endpoint fetches added $0.001 per page. The $10 free tier covers about 2,500 instant or 1,400 auto searches a month.

Exa Websets is billed separately as a subscription for building enriched lists of companies or people: Starter at $49/month (8,000 credits) and Pro at $449/month (100,000 credits), with Enterprise on request.

Sources: Exa pricing · Websets plans

Exa AI Review Verdict: Pros and Cons

Pros

  • Instant and fast search answered in about 0.8s, at $4–7 per 1,000 calls
  • Consistently returns primary sources over secondary coverage
  • Highlights, summaries and JSON-schema extraction cut tokens dramatically
  • Failed or blocked fetches cost nothing, and the MCP server is one click in Claude

Cons

  • Publish dates on only about 50% of results, some of them crawl dates
  • Cached content can be stale unless you set maxAgeHours: 0
  • Auto mode latency varied from 2s to 6.6s between two test days
  • /findSimilar now returns a deprecation header

Best for: agents that search inside tight loops and need canonical sources with minimal tokens.

Limitations: Public Web Access Only

I sent 8 URLs to the contents endpoint, once from cache and once with a forced live crawl:

Page type Cached (default) Live crawl
Public docs page Full content Full content
Practice site, logged out Full content Full content
LinkedIn feed Login wall Timeout error
GitHub account settings Login page Login page
Subreddit listing Blocked (SOURCE_NOT_AVAILABLE) Blocked
Amazon product page Full content, price included Full content
Instagram profile Blocked (SOURCE_NOT_AVAILABLE) Blocked
WSJ Tech section Headlines only Timeout error

Exa refuses some domains outright (SOURCE_NOT_AVAILABLE for Reddit and Instagram), but handled Amazon well, price included, which Tavily didn’t. Two details from the dashboard: blocked and timed-out fetches were billed $0, and every one of them still returned HTTP 200. The real error lives in the per-URL statuses array, so check it instead of the status code.

Exa request history for the limits test: blocked and timed-out URLs show HTTP 200 and $0 cost

What Exa can’t do is be someone. With no account, cookies or session, a LinkedIn feed, your CRM or a supplier portal all look the same: a sign-in form.

For authenticated web data extraction, you need a browser that holds a session.

The Gologin Bridge: Exa for Discovery, Gologin for Logged-In Pages

My limits test drew the line clearly. Reddit and Instagram came back as SOURCE_NOT_AVAILABLE, LinkedIn returned a login wall and GitHub settings showed a sign-in page. Exa behaved exactly as an anonymous fetcher should; those pages simply aren’t built for anonymous fetchers.

Gologin Cloud Browser covers that side. It loads pages in a real cloud browser tied to a saved profile, and you drive it over CDP with the Playwright or Puppeteer code you already run. Getting cookies back next session is standard across cloud browsers. What Gologin adds is continuity of identity: the device fingerprint and the residential IP stay the same from run to run, so a site sees one consistent returning visitor rather than a new machine on every request. The fingerprint is set inside Gologin’s own Chromium build instead of patched on at runtime, so the signals a site reads don’t contradict each other.

Gologin cloud browser

That consistency is what counts on the pages Exa couldn’t open. Protected sites react to visitors that look new, anonymous or inconsistent; a long-lived profile, signed in to your own account on a stable residential address, gives them nothing unusual to react to. Use it with your own accounts and within each site’s terms.

Exa Gologin Cloud Browser
Job Find the right public pages by meaning Read pages as the same signed-in user on every run
Session state None, every request is anonymous One fingerprint and one residential IP kept across runs, along with cookies and storage
Logged-in pages No Yes
Output JSON, text, highlights, summaries A live browser page you convert as needed
Integration REST, SDKs, MCP CDP (Playwright, Puppeteer), MCP server
Pricing shape Per request + per page Browser time plus residential proxy traffic at $1/GB beyond the plan allowance: two metered lines

Think of it as two lookups. Exa decides where to look across the open web; persistent browser sessions in Gologin read what’s there once you’re signed in. Both hand back text your model can use, so the agent never needs to know which one supplied it.

If a site asks for a one-time code or an approval halfway through a run, someone on your team can open the session’s live view, deal with it, and give control back to the agent without the profile losing its identity.

Code: From Exa Results to Signed-In Markdown

To keep the demo reproducible, it runs against quotes.toscrape.com, a practice site built for exactly this kind of test. Logged-in visitors get an extra “Goodreads page” link under each quote, which makes a handy proof that a page was read with the session intact. Because Exa’s includeDomains takes paths as well as domains, the search stays on the tag pages that carry that link.

The profile needs one sign-in before its first run. Either uncomment the first_login() line for that run, or open the session’s live view and log in by hand. Both store the session on the profile, so later runs skip this step.

pip install requests playwright beautifulsoup4 markdownify
import os
import requests
from bs4 import BeautifulSoup
from markdownify import markdownify
from playwright.sync_api import sync_playwright

EXA_KEY = os.environ["EXA_API_KEY"]
GL_TOKEN = os.environ["GL_API_TOKEN"]
PROFILE_ID = os.environ["GL_PROFILE_ID"]
CDP_URL = f"wss://cloudbrowser.gologin.com/connect?token={GL_TOKEN}&profile={PROFILE_ID}"
FALLBACK_URLS = ["https://quotes.toscrape.com/tag/love/",
                 "https://quotes.toscrape.com/tag/inspirational/"]

def discover(query):
    """Exa picks the pages; fall back to known URLs if the filter matches nothing."""
    resp = requests.post(
        "https://api.exa.ai/search",
        json={"query": query, "type": "instant", "numResults": 3,
              "includeDomains": ["quotes.toscrape.com/tag"]},
        headers={"x-api-key": EXA_KEY}, timeout=30,
    )
    urls = [r["url"] for r in resp.json().get("results", [])]
    # tag/love/ and tag/love/page/1/ are the same page: normalize, then dedupe in order
    urls = list(dict.fromkeys(u.replace("http://", "https://").replace("page/1/", "") for u in urls))
    if not urls:
        print("Exa returned 0 results for quotes.toscrape.com/tag, using fallback URLs")
    return urls or FALLBACK_URLS

def first_login(page, username, password):
    """Run once per profile. Afterwards the session lives on the profile."""
    page.goto("https://quotes.toscrape.com/login")
    page.fill("#username", username)
    page.fill("#password", password)
    page.click("input[type='submit']")

def to_markdown(html):
    soup = BeautifulSoup(html, "html.parser")
    for tag in soup(["script", "style", "nav", "header", "footer", "form"]):
        tag.decompose()
    blocks = soup.select("main, article, .col-md-8") or [soup.body]
    main = max(blocks, key=lambda el: len(el.get_text()))  # largest content block
    return markdownify(str(main), heading_style="ATX", strip=["img"])

def stop_profile():
    """Stop the cloud browser itself; browser.close() only disconnects Playwright."""
    resp = requests.delete(f"https://api.gologin.com/browser/{PROFILE_ID}/web",
                           headers={"Authorization": f"Bearer {GL_TOKEN}"}, timeout=30)
    print(f"cloud session stopped: HTTP {resp.status_code}")

urls = discover("quotes about love and inspiration")
with sync_playwright() as p:
    browser = page = None
    try:
        browser = p.chromium.connect_over_cdp(CDP_URL)
        page = browser.contexts[0].new_page()
        # first_login(page, os.environ["SITE_USER"], os.environ["SITE_PASS"])  # first run only
        for url in urls:
            page.goto(url, wait_until="domcontentloaded")
            signed_in = page.locator("a[href='/logout']").count() > 0
            md = to_markdown(page.content())
            print(f"{url} | signed in: {signed_in} | "
                  f"member links: {md.count('Goodreads page')} | ~{len(md) // 4} tokens")
    finally:
        if page:
            page.close()
        if browser:
            browser.close()
        stop_profile()

This is the log from a run on October 19, 2026, with the profile still signed in from its first session six days earlier:

https://quotes.toscrape.com/tag/love/ | signed in: True | member links: 10 | ~1318 tokens
https://quotes.toscrape.com/tag/inspirational/ | signed in: True | member links: 10 | ~1148 tokens
https://quotes.toscrape.com/tag/inspiration/ | signed in: True | member links: 1 | ~72 tokens
cloud session stopped: HTTP 204
Terminal output of the Exa + Gologin script after dedupe: three distinct tag pages signed in, cloud session stopped with HTTP 204

Exa’s path filter kept every result on tag pages, and the dedupe step in discover() collapses variants such as tag/love/ and tag/love/page/1/, so each page is fetched once. All three pages rendered the signed-in view: two full tag pages with 10 member-only links each, and the smaller inspiration tag, which holds a single quote and its one link. A False on signed in means the site expired the session, so repeat the first sign-in on the same profile and carry on.

Note what the finally block does: closing the page and calling browser.close() only detaches Playwright, and the cloud browser would keep running and billing. The DELETE call to Gologin’s API stops the instance itself, and the 204 at the end of the log is your confirmation.

Where the Markdown goes next depends on your pipeline:

  • index it in the same vector store as your Exa results,
  • expose it as a tool your agent calls for account-specific questions,
  • diff it on a schedule to catch changes on members-only pages.

FAQs

Is the Exa API free?

Every account gets $10 in credits each month with no card, enough for about 2,500 instant searches. Completing onboarding in the dashboard adds a one-time $10 bonus for your first team. Beyond that it’s pay as you go, with no subscription.

How much does the Exa API cost?

Search costs $4 (instant), $7 (fast or auto), $12 (deep) or $15 (deep-reasoning) per 1,000 requests, with up to 10 results included. Contents cost $1 per 1,000 pages per content type, and Answer costs $5 per 1,000.

Exa vs Tavily: which should I use?

In my tests, Exa was 2–5x faster in instant and fast modes and returned more primary sources. Tavily returned publish dates far more reliably (88% vs about 50%) and fits naturally into LangChain. Full numbers are in the Tavily review.

Exa vs Perplexity: what’s the difference?

Perplexity’s API is answer-first; Exa is source-first, returning ranked pages so you decide what the model sees. Exa’s /answer endpoint ($5 per 1,000) covers the answer case: in my test it answered a Fed question correctly in 2.3s, citing federalreserve.gov.

Exa vs Firecrawl?

Different steps: Exa finds pages by meaning; Firecrawl crawls and converts URLs you already have. Many pipelines use both.

Can Exa access pages behind a login?

No. It has no way to hold an account or a session, and it refuses some domains outright with SOURCE_NOT_AVAILABLE. The usual setup keeps Exa for discovery and routes logged-in pages to a browser profile that stays signed in, such as Gologin Cloud Browser.

Conclusion

This Exa AI review comes down to speed and sources. In my tests Exa reached the canonical page faster than Tavily, and it gives you precise control over how much of that page reaches your model.

But it only sees what an anonymous visitor sees.

Use Exa to find the right pages. Use Gologin Cloud Browser to open the ones behind a login as a returning, signed-in user, and hand both to your agent as clean Markdown.

Try Gologin Cloud Browser free →