exa.ai-websearch-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Exa API Setup Guide

Exa API 设置指南

Exa | Web Search API, AI Search Engine, & Website Crawler
Exa | 网页搜索API、AI搜索引擎与网站爬虫

Your Configuration

你的配置

SettingValue
Coding ToolOther
FrameworkcURL
Use CaseCoding agent, Agetnic AI, Open Claw
Search TypeAuto - Balanced relevance and speed (~1 second)
ContentFull text
设置项
编码工具其他
框架cURL
使用场景编码Agent、Agentic AI、Open Claw
搜索类型Auto - 平衡相关性与速度(约1秒)
内容全文

Keywords

关键词

ai search engine,serp api,best ai search engine,search api,deep research api,web search api,web search ai,ai search api,deepresearch api,web crawling api,website crawler,metaphor,exa,api,search,ai,llms

ai search engine,serp api,best ai search engine,search api,deep research api,web search api,web search ai,ai search api,deepresearch api,web crawling api,website crawler,metaphor,exa,api,search,ai,llms

API Key Setup

API密钥设置

Environment Variable

环境变量

bash
export EXA_API_KEY="YOUR_API_KEY"
bash
export EXA_API_KEY="YOUR_API_KEY"

.env File

.env 文件

env
EXA_API_KEY=YOUR_API_KEY

env
EXA_API_KEY=YOUR_API_KEY

🔌 Exa MCP Server

🔌 Exa MCP 服务器

Give your AI coding assistant real-time web search with Exa MCP.
Remote MCP URL:
https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY
Available tools:
web_search_exa
,
get_code_context_exa
,
company_research_exa
,
crawling_exa
,
linkedin_search_exa
,
deep_researcher_start
HTTP config (Cursor, Claude Code, Codex):
json
{
  "mcpServers": {
    "exa": {
      "type": "http",
      "url": "https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY",
      "headers": {}
    }
  }
}
Local install (Claude Desktop):
json
{
  "mcpServers": {
    "exa": {
      "command": "npx",
      "args": ["-y", "exa-mcp-server"],
      "env": { "EXA_API_KEY": "YOUR_API_KEY" }
    }
  }
}

为你的AI编码助手通过Exa MCP提供实时网页搜索能力。
远程MCP地址:
https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY
可用工具:
web_search_exa
,
get_code_context_exa
,
company_research_exa
,
crawling_exa
,
linkedin_search_exa
,
deep_researcher_start
HTTP配置(Cursor、Claude Code、Codex):
json
{
  "mcpServers": {
    "exa": {
      "type": "http",
      "url": "https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY",
      "headers": {}
    }
  }
}
本地安装(Claude Desktop):
json
{
  "mcpServers": {
    "exa": {
      "command": "npx",
      "args": ["-y", "exa-mcp-server"],
      "env": { "EXA_API_KEY": "YOUR_API_KEY" }
    }
  }
}
📖 完整文档:docs.exa.ai/reference/exa-mcp

Quick Start (cURL)

快速开始(cURL)

cURL

cURL

bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "React hooks best practices 2024",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'

bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "React hooks best practices 2024",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'

Function Calling / Tool Use

函数调用 / 工具使用

Function calling (also known as tool use) allows your AI agent to dynamically decide when to search the web based on the conversation context. Instead of searching on every request, the LLM intelligently determines when real-time information would improve its response—making your agent more efficient and accurate.
Why use function calling with Exa?
  • Your agent can ground responses in current, factual information
  • Reduces hallucinations by fetching real sources when needed
  • Enables multi-step reasoning where the agent searches, analyzes, and responds
函数调用(也称为工具使用)允许你的AI Agent根据对话上下文动态决定何时进行网页搜索。无需每次请求都搜索,LLM会智能判断何时需要实时信息来提升响应质量——让你的Agent更高效、准确。
为什么要结合Exa使用函数调用?
  • 你的Agent可以基于当前真实信息生成响应
  • 在需要时获取真实来源,减少幻觉
  • 支持多步骤推理,Agent可以先搜索、分析,再给出响应

OpenAI Function Calling

OpenAI 函数调用

python
import json
from openai import OpenAI
from exa_py import Exa

openai = OpenAI()
exa = Exa()

tools = [{
    "type": "function",
    "function": {
        "name": "exa_search",
        "description": "Search the web for current information.",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string", "description": "Search query"}},
            "required": ["query"]
        }
    }
}]

def exa_search(query: str) -> str:
    results = exa.search(query=query, type="auto", num_results=10, contents={"text": {"max_characters": 20000}})
    return "\n".join([f"{r.title}: {r.url}" for r in results.results])

messages = [{"role": "user", "content": "What's the latest in AI safety?"}]
response = openai.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)

if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    search_results = exa_search(json.loads(tool_call.function.arguments)["query"])
    messages.append(response.choices[0].message)
    messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": search_results})
    final = openai.chat.completions.create(model="gpt-4o", messages=messages)
    print(final.choices[0].message.content)
python
import json
from openai import OpenAI
from exa_py import Exa

openai = OpenAI()
exa = Exa()

tools = [{
    "type": "function",
    "function": {
        "name": "exa_search",
        "description": "Search the web for current information.",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string", "description": "Search query"}},
            "required": ["query"]
        }
    }
}]

def exa_search(query: str) -> str:
    results = exa.search(query=query, type="auto", num_results=10, contents={"text": {"max_characters": 20000}})
    return "\n".join([f"{r.title}: {r.url}" for r in results.results])

messages = [{"role": "user", "content": "What's the latest in AI safety?"}]
response = openai.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)

if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    search_results = exa_search(json.loads(tool_call.function.arguments)["query"])
    messages.append(response.choices[0].message)
    messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": search_results})
    final = openai.chat.completions.create(model="gpt-4o", messages=messages)
    print(final.choices[0].message.content)

Anthropic Tool Use

Anthropic 工具使用

python
import anthropic
from exa_py import Exa

client = anthropic.Anthropic()
exa = Exa()

tools = [{
    "name": "exa_search",
    "description": "Search the web for current information.",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "Search query"}},
        "required": ["query"]
    }
}]

def exa_search(query: str) -> str:
    results = exa.search(query=query, type="auto", num_results=10, contents={"text": {"max_characters": 20000}})
    return "\n".join([f"{r.title}: {r.url}" for r in results.results])

messages = [{"role": "user", "content": "Latest quantum computing developments?"}]
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)

if response.stop_reason == "tool_use":
    tool_use = next(b for b in response.content if b.type == "tool_use")
    tool_result = exa_search(tool_use.input["query"])
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": [{"type": "tool_result", "tool_use_id": tool_use.id, "content": tool_result}]})
    final = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)
    print(final.content[0].text)

python
import anthropic
from exa_py import Exa

client = anthropic.Anthropic()
exa = Exa()

tools = [{
    "name": "exa_search",
    "description": "Search the web for current information.",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "Search query"}},
        "required": ["query"]
    }
}]

def exa_search(query: str) -> str:
    results = exa.search(query=query, type="auto", num_results=10, contents={"text": {"max_characters": 20000}})
    return "\n".join([f"{r.title}: {r.url}" for r in results.results])

messages = [{"role": "user", "content": "Latest quantum computing developments?"}]
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)

if response.stop_reason == "tool_use":
    tool_use = next(b for b in response.content if b.type == "tool_use")
    tool_result = exa_search(tool_use.input["query"])
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": [{"type": "tool_result", "tool_use_id": tool_use.id, "content": tool_result}]})
    final = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)
    print(final.content[0].text)

Search Type Reference

搜索类型参考

TypeBest ForSpeedDepth
fast
Real-time apps, autocomplete, quick lookupsFastestBasic
auto
Most queries - balanced relevance & speedMediumSmart
Tip:
type="auto"
works well for most queries. It provides balanced relevance and speed.

类型适用场景速度深度
fast
实时应用、自动补全、快速查询最快基础
auto
大多数查询 - 平衡相关性与速度中等智能
提示:
type="auto"
适用于大多数查询,它能提供相关性与速度的平衡。

Content Configuration

内容配置

Choose ONE content type per request (not both):
TypeConfigBest For
Text
"text": {"max_characters": 20000}
Full content extraction, RAG
Highlights
"highlights": {"max_characters": 2000}
Snippets, summaries, lower cost
⚠️ Token usage warning: Using
text: true
(full page text) can significantly increase token count, leading to slower and more expensive LLM calls. To mitigate:
  • Add
    max_characters
    limit:
    "text": {"max_characters": 10000}
  • Use
    highlights
    instead if you don't need contiguous text
When to use text vs highlights:
  • Text - When you need untruncated, contiguous content (e.g., code snippets, full articles, documentation)
  • Highlights - When you need key excerpts and don't need the full context (e.g., summaries, Q&A, general research)

每次请求仅能选择一种内容类型(不可同时选两种):
类型配置适用场景
文本
"text": {"max_characters": 20000}
完整内容提取、RAG
高亮片段
"highlights": {"max_characters": 2000}
片段摘要、总结、低成本
⚠️ Token使用警告: 使用
text: true
(完整页面文本)会显著增加Token数量,导致LLM调用更慢、成本更高。可通过以下方式缓解:
  • 添加
    max_characters
    限制:
    "text": {"max_characters": 10000}
  • 若不需要连续文本,可改用
    highlights
何时使用文本 vs 高亮片段:
  • 文本 - 当你需要完整、连续的内容时(例如代码片段、完整文章、文档)
  • 高亮片段 - 当你只需要关键摘录,不需要完整上下文时(例如摘要、问答、通用研究)

Domain Filtering (Optional)

域名过滤(可选)

Usually not needed - Exa's neural search finds relevant results without domain restrictions.
When to use:
  • Targeting specific authoritative sources
  • Excluding low-quality domains from results
Example:
json
{
  "includeDomains": ["arxiv.org", "github.com"],
  "excludeDomains": ["pinterest.com"]
}
Note:
includeDomains
and
excludeDomains
cannot be used together.

通常不需要 - Exa的神经搜索无需域名限制即可找到相关结果。
何时使用:
  • 针对特定权威来源
  • 从结果中排除低质量域名
示例:
json
{
  "includeDomains": ["arxiv.org", "github.com"],
  "excludeDomains": ["pinterest.com"]
}
注意:
includeDomains
excludeDomains
不能同时使用。

Coding Agent

编码Agent

Use
category: "null"
to search for null content.
json
{
  "query": "React hooks best practices 2024",
  "category": null,
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}
Tips:
  • Use
    type: "auto"
    for balanced results
  • Great for documentation lookup, API references, code examples
使用
category: "null"
来搜索无分类内容。
json
{
  "query": "React hooks best practices 2024",
  "category": null,
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}
提示:
  • 使用
    type: "auto"
    获取平衡结果
  • 非常适合文档查询、API参考、代码示例

SDK Examples

SDK示例



Category Examples

分类示例

Use category filters to search dedicated indexes. Each category returns only that content type.
Note: Categories can be restrictive. If you're not getting enough results, try searching without a category first, then add one if needed.
使用分类过滤器搜索特定类型的内容索引。每个分类仅返回对应类型的内容。
注意: 分类过滤器有一定局限性。如果没有得到足够结果,建议先不使用分类过滤器,之后再根据需要添加。

People Search (
category: "people"
)

人物搜索 (
category: "people"
)

Find people by role, expertise, or what they work on
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "software engineer distributed systems",
  "category": "people",
  "type": "auto",
  "num_results": 10
}'
Tips:
  • Use SINGULAR form
  • Describe what they work on
  • No date/text filters supported
根据角色、专业领域或工作内容查找人物
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "software engineer distributed systems",
  "category": "people",
  "type": "auto",
  "num_results": 10
}'
提示:
  • 使用单数形式
  • 描述其工作内容
  • 不支持日期/文本过滤器

Company Search (
category: "company"
)

公司搜索 (
category: "company"
)

Find companies by industry, criteria, or attributes
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "AI startup healthcare",
  "category": "company",
  "type": "auto",
  "num_results": 10
}'
Tips:
  • Use SINGULAR form
  • Simple entity queries
  • Returns company objects, not articles
根据行业、标准或属性查找公司
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "AI startup healthcare",
  "category": "company",
  "type": "auto",
  "num_results": 10
}'
提示:
  • 使用单数形式
  • 简单的实体查询
  • 返回公司对象,而非文章

News Search (
category: "news"
)

新闻搜索 (
category: "news"
)

News articles
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "OpenAI announcements",
  "category": "news",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
Tips:
  • Use livecrawl: "preferred" for breaking news
  • Avoid date filters unless required
新闻文章
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "OpenAI announcements",
  "category": "news",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
提示:
  • 对于突发新闻,使用livecrawl: "preferred"
  • 除非必要,避免使用日期过滤器

Research Papers (
category: "research paper"
)

研究论文搜索 (
category: "research paper"
)

Academic papers
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "transformer architecture improvements",
  "category": "research paper",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
Tips:
  • Use type: "auto" for most queries
  • Includes arxiv.org, paperswithcode.com, and other academic sources
学术论文
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "transformer architecture improvements",
  "category": "research paper",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
提示:
  • 大多数查询使用type: "auto"
  • 包含arxiv.org、paperswithcode.com及其他学术来源

Tweet Search (
category: "tweet"
)

推文搜索 (
category: "tweet"
)

Twitter/X posts
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "AI safety discussion",
  "category": "tweet",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
Tips:
  • Good for real-time discussions
  • Captures public sentiment

Twitter/X帖子
bash
curl -X POST 'https://api.exa.ai/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "AI safety discussion",
  "category": "tweet",
  "type": "auto",
  "num_results": 10,
  "contents": {
    "text": {
      "max_characters": 20000
    }
  }
}'
提示:
  • 适合实时讨论
  • 捕捉公众情绪

Content Freshness (maxAgeHours)

内容新鲜度(maxAgeHours)

maxAgeHours
sets the maximum acceptable age (in hours) for cached content. If the cached version is older than this threshold, Exa will livecrawl the page to get fresh content.
ValueBehaviorBest For
24Use cache if less than 24 hours old, otherwise livecrawlDaily-fresh content
1Use cache if less than 1 hour old, otherwise livecrawlNear real-time data
0Always livecrawl (ignore cache entirely)Real-time data where cached content is unusable
-1Never livecrawl (cache only)Maximum speed, historical/static content
(omit)Default behavior (livecrawl as fallback if no cache exists)Recommended — balanced speed and freshness
When LiveCrawl Isn't Necessary: Cached data is sufficient for many queries, especially for historical topics or educational content. These subjects rarely change, so reliable cached results can provide accurate information quickly.
See maxAgeHours docs for more details.

maxAgeHours
用于设置缓存内容的最大可接受时长(小时)。如果缓存版本超过这个阈值,Exa会实时爬取页面以获取新鲜内容。
行为适用场景
24若缓存不足24小时则使用缓存,否则实时爬取每日更新的内容
1若缓存不足1小时则使用缓存,否则实时爬取近实时数据
0始终实时爬取(完全忽略缓存)缓存内容不可用的实时数据场景
-1从不实时爬取(仅使用缓存)追求最大速度的历史/静态内容
(省略)默认行为(若无缓存则实时爬取作为 fallback)推荐 —— 平衡速度与新鲜度
何时无需实时爬取: 缓存数据适用于许多查询场景,尤其是历史主题或教育内容。这些内容很少变化,可靠的缓存结果可以快速提供准确信息。
更多细节请查看maxAgeHours文档

Other Endpoints

其他端点

Beyond
/search
, Exa offers these endpoints:
EndpointDescriptionDocs
/contents
Get contents for known URLsDocs
/answer
Q&A with citations from web searchDocs
Example - Get contents for URLs:
json
POST /contents
{
  "urls": ["https://example.com/article"],
  "text": { "max_characters": 20000 }
}

除了
/search
,Exa还提供以下端点:
端点描述文档
/contents
获取已知URL的内容文档
/answer
结合网页搜索结果的问答(带引用)文档
示例 - 获取URL内容:
json
POST /contents
{
  "urls": ["https://example.com/article"],
  "text": { "max_characters": 20000 }
}

Troubleshooting

故障排除

Results not relevant?
  1. Try
    type: "auto"
    - most balanced option
  2. Refine query - use singular form, be specific
  3. Check category matches your use case
Results too slow?
  1. Use
    type: "fast"
  2. Reduce
    num_results
  3. Skip contents if you only need URLs
No results?
  1. Remove filters (date, domain restrictions)
  2. Simplify query
  3. Try
    type: "auto"
    - has fallback mechanisms

结果不相关?
  1. 尝试
    type: "auto"
    ——最平衡的选项
  2. 优化查询——使用单数形式,更具体
  3. 检查分类是否匹配你的使用场景
结果速度太慢?
  1. 使用
    type: "fast"
  2. 减少
    num_results
    数量
  3. 若仅需URL,可跳过内容获取
无结果返回?
  1. 移除过滤器(日期、域名限制)
  2. 简化查询
  3. 尝试
    type: "auto"
    ——它有 fallback 机制

Resources

资源