
这篇文章不是软文——SerpApi 本身也不是什么新鲜玩意儿了。写的是实打实的工程经验:认证怎么过、返回的 JSON 结构到底长啥样、额度怎么省、LangChain 里怎么接,以及那些文档里不会写但人人都踩的坑。
如果你正在做 AI Agent、SEO 工具、比价爬虫,或者任何需要搜索数据的产品,这篇值得花 5 分钟看完。
SerpApi 的认证是整个流程里最简单的部分了——一个 API Key,往 URL 参数里一塞就完事。没有 OAuth,没有 Bearer Token,也不用装什么 SDK。但简单归简单,Key 管理不能含糊。
const params = new URLSearchParams({
engine: 'google',
q: 'javascript developer advocate',
api_key: process.env.SERPAPI_API_KEY // 永远不要硬编码
});
const response = await fetch(`https://serpapi.com/search?${params}`);
const data = await response.json();
Key 放环境变量里,别碰源码,更别提交到公开仓库。获取方式也很常规:注册账号 → Dashboard → Your API Key。免费版每月 100 次搜索,拿到就能用。
直接写调用当然可以,但生产环境里需要一个封装好的 search 函数来处理参数和异常:
async function search(query, options = {}) {
const params = new URLSearchParams({
engine: 'google',
q: query,
api_key: process.env.SERPAPI_API_KEY,
num: options.num || 10,
hl: options.language || 'en',
gl: options.country || 'us',
...options
});
const res = await fetch(`https://serpapi.com/search?${params}`);
if (!res.ok) {
const error = await res.json();
throw new Error(`SerpApi error: ${error.error}`);
}
return res.json();
}
const results = await search('web scraping api javascript');
console.log(results.organic_results[0]);
这是最容易被忽略的地方。SerpApi 的文档把字段列表列出来了,但没告诉你哪些字段是"可能不存在"的——结果线上很多人一访问就报错。
{
"search_metadata": { "id": "...", "status": "Success", "total_time_taken": 1.23 },
"search_parameters": { "engine": "google", "q": "your query" },
"organic_results": [
{ "position": 1, "title": "Result title", "link": "https://...", "snippet": "Description text..." }
],
"related_searches": [...],
"pagination": { "next": "https://serpapi.com/search?..." }
}
核心原则:永远先检查字段是否存在再访问。
const answer = results.answer_box?.answer ?? null;
const organicResults = results.organic_results ?? [];
最常见的 bug:搜索结果只返回图片、FAQ 或者 AI 摘要,就是没有正常的自然搜索结果。问题根源是 location 参数不明确。
修复方案一:显式设置 location
const params = new URLSearchParams({
engine: 'google',
q: 'your query',
location: 'Austin, Texas, United States',
google_domain: 'google.com',
gl: 'us',
hl: 'en',
api_key: process.env.SERPAPI_API_KEY
});
修复方案二:用 Locations API 查找正确的 location 字符串
const locationRes = await fetch(`https://serpapi.com/locations.json?q=Austin&limit=5`);
const locations = await locationRes.json();
修复方案三:直接看返回里有什么字段
const fields = Object.keys(results);
console.log('Available fields:', fields);
SerpApi 按次收费,大规模使用时额度管理是真实存在的问题。
查看剩余额度
async function getAccountInfo() {
const res = await fetch(`https://serpapi.com/account?api_key=${process.env.SERPAPI_API_KEY}`);
const account = await res.json();
return { searchesUsed: account.searches_this_month, creditsRemaining: account.plan_searches_left };
}
缓存结果避免重复请求
const cache = new Map();
async function cachedSearch(query, ttlMs = 3600000) {
const cacheKey = query.toLowerCase().trim();
const cached = cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < ttlMs) return cached.data;
const data = await search(query);
cache.set(cacheKey, { data, timestamp: Date.now() });
return data;
}
SerpApi 在 2026 年 4 月支持了 llms.txt,明显是在朝 AI Agent 这个方向做适配。以下是接入 LangChain 的基本写法:
import { SerpAPI } from "@langchain/community/tools/serpapi";
import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { pull } from "langchain/hub";
const searchTool = new SerpAPI(process.env.SERPAPI_API_KEY, { location: "United States" });
const llm = new ChatOpenAI({ model: "gpt-4", temperature: 0 });
const agent = await createOpenAIFunctionsAgent({ llm, tools: [searchTool], prompt: await pull("hwchase17/openai-functions-agent") });
const executor = new AgentExecutor({ agent, tools: [searchTool] });
const result = await executor.invoke({ input: "What are the latest developments in JavaScript developer tooling?" });
async function safeSearch(query, options = {}) {
try {
return await search(query, options);
} catch (err) {
if (err.message.includes('429')) { await new Promise(r => setTimeout(r, 60000)); return search(query, options); }
if (err.message.includes('Invalid API key')) throw new Error('检查 SERPAPI_API_KEY 环境变量');
if (err.message.includes('Your account has run out')) throw new Error('SerpApi 额度已耗尽');
throw err;
}
}
原文:Your First SerpApi Integration in JavaScript — From Hello World to Production