做过 SEO 排名监控、广告竞品分析或者舆情数据整理的人大概率都在 Google SERP API 这个环节卡过预算。Google 官方搜索接口的价格看着不高但限制一堆老牌第三方服务功能齐全可月费一上来就是几十上百美元查询量稍微大一点账单直接起飞。所以“最便宜的 Google SERP API”这个话题我基本逢人就聊今天就把自己试过的几个低价方案、自建方案的账以及接入时容易踩的坑一次性理清楚。这篇文章适合谁打算做排名追踪工具、给团队搭竞品情报系统或者想低成本验证一个和搜索引擎数据相关的想法的人都可以参考。先放个结论再展开真正便宜不是一个固定答案而是“单价、最低消费、字段完整度”这三个变量算出来的结果。前两部分讲选型思路和市面价格第三部分讲自建方案的成本账第四部分是能直接抄的接入代码最后整理跑批常见问题和排查方法。1. SERP API 到底在卖什么理清单价之前先看字段1.1 SERP 不是十根蓝链很多人第一次接触 SERP API 时会想Google 搜索结果页不就是十个链接地址吗我自己用 requests 抓一下不就行了但真实情况是一个完整的搜索结果页在前端至少包含自然结果organic results、付费广告位ads、本地商家包local pack、知识图谱knowledge graph、精选摘要featured snippet / answer box、相关搜索related searches还可能混入图片、视频、购物这些垂直板块。不同 API 愿意把这些字段返回得多细直接决定了它值不值这个价。比如你想监控某品牌词的本地门店排名local pack 里的门店卡片、地图、评分这些字段官方接口和很多低价接口压根不提供你想看某个词下面对方投了哪些广告语又得有 ads 相关返回值。只看十根蓝链的场景用官方接口甚至自己抓就够了要拿到本地商家排名或知识图谱这类结构化数据那就只能靠第三方服务或者自己解析搜索结果页。这也是为什么 SERP API 的价格能从每千次两三美元拉到三四十美元差异基本都由字段完整度决定。1.2 三种获取方式的成本结构完全不同在比价之前我建议先把获取 Google 搜索结果的三种主流方式放在一起看一遍。我把它们的成本结构整理成了下面的表格方便直接对照。方案大致单价数据完整度运维成本适合的场景官方 Custom Search JSON API约 $5/千次前 100 次/天免费低主要是文本自然结果几乎为零轻量搜词、原型验证、站内搜索第三方 SERP API约 $2.5~$15/千次因服务商而异高多数覆盖广告、图谱、相关搜索几乎为零生产环境、需要垂直数据、不想维护抓取层自建抓取边际成本接近零主要花在出口 IP 和人的时间上中到高取决于解析实现高大查询量、长尾监控、数据质量可控的场景这三类的定位从这张表基本能看出来。官方接口适合轻量调用第三方适合省心跑生产自建适合把每一分钱都花在“请求本身”而不是“服务溢价”上的人。这不是说价格越便宜越好而是先要弄清楚自己的需求在哪个象限。比如你做的是广告情报那字段完整度优先级就极高选型时要往第三方高配走如果只是给内部小工具补一点搜索数据自建反而更灵活。1.3 官方 API 的“便宜”只是表象官方 Custom Search JSON API 前 100 次/天免费超量后每千次 5 美元价格确实不贵。但它有三个足以让人直接放弃的理由。第一默认输出最多 10 条自然结果即便靠 start 参数翻页Google 最多也只给你前 100 条。对于需要“复刻真实搜索结果页”的排名追踪来说这个深度远远不够。第二它需要先创建一个 Programmable Search Engineengine id简称 CX而且默认是站点限定搜索想搜全网还得去后台手动配置“search the entire web”很多人第一次接就栽在这。第三也是最关键的它拿不到 ads、knowledge_graph、related_searches 这些对 SEO 和广告分析极有价值的数据同时不支持地图、图片、购物等垂直搜索场景。一句话总结官方接口的目标不是给你“复刻 Google 搜索页”而是给你一个受控的站点搜索或全网检索接口。当你的业务需要看到用户实际看到的那一页时只能向外看。2. 市面低价 SERP API 横评价格很低但里面有四个坑2.1 先看单价带宽第三方 SERP API 之所以能收钱是因为它帮你把字段完整度和稳定性这块补上了。那市面上的价格水分到底有多少我按当时看到的公开价格整理了一下单位统一折算到“每千次查询”。价格变动很频繁具体以官网为准。服务商大致起步套餐免费额度折合千次价特点SerpAPI$75/月约 5000 次100 次/月约 $15/千次老牌、字段全、文档和 SDK 完善ValueSerp$25/月约 10000 次100 次/月约 $2.5/千次低价定位基础 SERP 够用Serper$29 档约 5000 次上下免费额度较大约 $5/千次上下接口简单、返回结构干净SearchApi.io$49/月约 10000 次100 次/月约 $4.9/千次引擎覆盖广Google News 等垂直场景多Zenserp$60/月约 5000 次50 次/月约 $12/千次垂直场景丰富企业级Bright Data、Oxylabs 等按量计费视套餐而定$20/千次稳定、覆盖全球出口 IP、合规能力强只看这张表结论很清晰ValueSerp、Serper、SearchApi 这三家基本就是普通第三方里最便宜的一档按次单价能压到 3 到 5 美元。但“最便宜”这三个字背后还有隐藏变量下面逐个说。2.2 最低消费和套餐浪费比单价更容易踩很多服务都不是按次给你零售而是“月费买配额没用完不结转”。这意味着你实际上要为一大部分用不完的查询买单。举个例子某服务单价折合 5 美元/千次但最低套餐是 29 美元/月含 5000 次。如果你的真实用量只有 1000 次那实际成本就是 29 美元/千次瞬间贵了 6 倍。所以我的建议是选套餐前先做三个估算。一是预计月查询量二是业务峰值缓冲三是缓存命中率缓存命中越多实际要去服务商那边下单的次数就越少。把这三项算完你才知道该买多大套餐而不是单纯被宣传页上的“低至 X 美元/千次”打动。我在这个环节上见过不止一个团队因为套餐买太大到期一算每千次成本比老牌服务还贵属于典型的“被便宜单价带了节奏”。2.3 字段缺、限速、共享出口 IP便宜换来的是不确定性价格低必然有代价我从实际体验总结出四个常见问题。第一共享出口 IP 池。低价服务为了摊薄成本会用一批共享的出口 IP 去请求搜索页。平时没问题可一旦这批 IP 被反爬策略盯上连坐效应马上出现——你可能什么都没干请求就开始大量返回验证码或空 organic。第二字段被阉割。有些低价套餐文档里写着“最多返回前 10 条自然结果”没有 ads没有 related_searches买回来才发现满足不了需求。第三限速严重。低价套餐的并发通常只有 1 到 5意味着千次单价再便宜一小时也跑不了多少量适合小批跑不适合批量灌数据。第四客服基本靠文档。低价服务大多没有工单 SLA出问题只能自己翻文档紧急场景会比较难受。这四条不是劝退而是提醒把低价 API 当生产主力之前先拿几百次查询测一测看返回字段、成功率、延迟是否都能扛住业务需求。很多服务商的对比页里不会写这些细节只有实际跑过才知道。3. 比拼单价更狠的做法自建抓取把边际成本压到接近零3.1 自建不是“写个爬虫”是“写数据管道”聊完第三方再聊更硬核的方案自己抓 Google 搜索页。很多人一听这个就兴奋觉得终于不用月月交钱。但我想先泼一点冷水自建 SERP 抓取难点不在“请求一个页面”而在“持续稳定地请求大量页面”。一套能跑进生产环境的自建方案至少要包含出口 IP 的轮换策略、UA 和浏览器指纹伪装、失败重试、结果解析、缓存、监控告警、结果入库。把它当成一个小型数据管道来设计而不是一个爬虫脚本。如果你只是每天几百次查询一台小云主机加上 requests 或 Playwright 加缓存完全够用只有当你要做高并发、低延迟、海量关键词监控时自建的复杂度才会指数上升。3.2 一份最小可用的抓取参考下面这段是用 requests 直接请求 Google 搜索页的示范。它最直观但也是最容易被反爬拦下的写法。生产环境请至少加上缓存、随机延时和失败重试。import requests from bs4 import BeautifulSoup headers { User-Agent: ( Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 ), Accept-Language: en-US,en;q0.9, } res requests.get( https://www.google.com/search, params{q: local seo tools, num: 20, gl: us, hl: en}, headersheaders, timeout15, ) res.raise_for_status() soup BeautifulSoup(res.text, html.parser) for item in soup.select(div.MjjYud): title_el item.select_one(h3) link_el item.select_one(a) if title_el and link_el and link_el.get(href, ).startswith(http): print(title_el.get_text(stripTrue), link_el[href])需要说明的是Google 前端的 class 名换得比较频繁我在不同时期分别见过 div.g、div.MjjYud 等结构。别把 CSS 选择器写死更好的做法是解析 div#search 容器后用链接和标题的 HTML 结构特征去定位结果块而不是依赖某个具体 class。如果不想维护这套解析可以引入开源的 search-engine-parser 这类库。如果你的查询量不大但很在意渲染稳定性用 Playwright 会省心一些。无头浏览器虽然重但能直接拿到包括 JS 渲染后的完整结构。from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page() page.goto(https://www.google.com/search?qlocalseotoolsglushlen) page.wait_for_selector(div#search) print(page.text_content(div#search)[:2000]) browser.close()真实项目里我推荐 requests 抓 HTML 为主、Playwright 兜底两种模式并存。纯 requests 快很多但遇到需要执行 JS 的页面或特殊验证时无头浏览器能帮流程续上。3.3 自建成本账服务器、出口 IP、维护时间自建的“价格”不是免费而是换了记账科目。我把常见的成本拆开列一下。云主机低配 VPS 一个月几美元到二十美元不等主要看你在哪个地区部署、需要多大带宽。出口 IP 资源静态数据中心 IP 便宜但被反爬盯上的概率高住宅 IP 资源按量或按带宽计费单价明显更高但请求质量稳定很多。如果你的业务主要围绕美国市场尽量用和 Google 页面语言、时区匹配的出口 IP 环境。维护时间这部分最贵。搜索页结构会变、反爬策略会变、验证码形式会变每变一次你都要花时间跟进。这个成本不体现在账面上但体现在你是不是天天加班。我算过一笔账如果每天 1000 次查询来源集中在几百个关键词上自建的“服务器和少量付费出口 IP”成本可以压到每月 15 到 30 美元比第三方按量付费便宜不少。但前提是你接受“每周可能花 2 到 3 小时维护”的时间成本。如果你的主业不是搞搜索引擎数据这笔时间成本往往比省下的月费更贵。3.4 我的建议先第三方后自建不要一上来就囤服务器我见过不少团队在业务刚起步时就急着自建结果数据管道还没跑顺核心业务已经延后了。我的建议是反着来先用第三方低价 API 把业务跑通验证清楚流量模型和查询量再在合适的位置插入缓存最后才考虑要不要自建抓取层。这样能用最低的风险验证假设等真的到了“每天几万次查询”的规模自建的收益才会明显超过维护成本。顺序搞对省钱才是真的省。4. 接入实操一套 Python 客户端吃下大多数低价 API4.1 注册与取 key 的注意点选好服务商之后第一步是注册并拿到 API key。这里有几个容易被忽略的细节一是很多服务商允许你把 key 绑定 IP 白名单如果你在多个地方部署记得把出口 IP 都加进去否则换环境就 403二是免费额度是用来做连通性测试的不是用来顶生产的别拿免费 key 去跑正式任务三是 key 一定要放到环境变量或密钥管理服务里别硬编码进代码仓库我每年都能看到几个因为 key 泄露被刷爆账单的案例。SERP API 的 key 泄露和云厂商的 AccessKey 泄露一样都是低概率高损失的事故。4.2 统一调用层一次封装随意换服务商不同低价 API 的请求风格主要分两种GET 型参数塞在 URL 里key 放在 query 或 header和 POST 型JSON body 加自定义鉴权头。最省心的做法是封装一个统一客户端把鉴权、超时、重试都收拢到一起后面换服务商只改配置不改业务代码。import time import requests class CheapSerpClient: 统一的 Google SERP 客户端。 默认按 POST 风格调用类似 serper.dev 的接口 endpoint: POST https://google.serper.dev/search header: X-API-KEY body: {q: ..., gl: us, hl: en, num: 10} 换成 GET 风格服务如 valueserp 或 searchapi.io时 只需要自备一个 build_request 方法把参数塞进 URL。 def __init__( self, api_key, endpointhttps://google.serper.dev/search, timeout20, max_retries3 ): self.api_key api_key self.endpoint endpoint self.timeout timeout self.max_retries max_retries def search(self, q, glus, hlen, num10, **extra): payload {q: q, gl: gl, hl: hl, num: num, **extra} headers { X-API-KEY: self.api_key, Content-Type: application/json, } last_exc None for attempt in range(self.max_retries): try: res requests.post( self.endpoint, jsonpayload, headersheaders, timeoutself.timeout ) if res.status_code in (429, 403, 500, 502, 503) and attempt self.max_retries - 1: time.sleep(2 ** attempt) continue res.raise_for_status() return res.json() except requests.RequestException as exc: last_exc exc if attempt self.max_retries - 1: time.sleep(2 ** attempt) raise last_exc这段代码里重试用了简单的指数退避429、403、5xx 都会退避后重试其他错误直接抛给上层。生产环境你还可以把退避时间加入随机抖动避免一批任务在同一时刻集体重试把服务商接口打爆。4.3 返回字段解析标准化成自己的数据模型第三方 API 的返回字段命名五花八门我见过 organic、organic_results、results 三种叫法分别指自然结果。为了避免业务层跟着服务商字段走建议在客户端里做一次标准化把关键字段统一成自己的字典结构。def normalize_serp(raw: dict): 把不同服务的 SERP 响应归一化成统一结构。 organic ( raw.get(organic_results) or raw.get(organic) or raw.get(results) or [] ) return { query: raw.get(searchParameters) or raw.get(search_parameters) or {}, total_results: ( raw.get(search_information, {}).get(total_results) if isinstance(raw.get(search_information), dict) else raw.get(total_results) ), organic: [ { position: item.get(position, idx 1), title: item.get(title, ), url: item.get(link) or item.get(url), snippet: item.get(snippet, ), } for idx, item in enumerate(organic) ], ads: raw.get(ads) or raw.get(paid_results) or [], related_searches: raw.get(related_searches) or raw.get(relatedSearches) or [], knowledge_graph: raw.get(knowledge_graph) or raw.get(knowledgeGraph) or None, }规范之后业务层只需要关心这一套固定的键名不会因为换服务商而重写解析逻辑。强烈建议把这段归一化函数写进客户端而不是业务代码它能把你未来换供应商的成本压到最低。我见过很多项目没做这层抽象导致每个服务商各写一套解析维护起来非常痛苦。4.4 缓存省钱的另一半缓存是 SERP 预算里最容易被忽略的省钱手段。排名追踪和竞品分析这类场景关键词集合通常固定查询重复率非常高。我见过一个项目在加了一层 SQLite 缓存之后第三方 API 费用直接下降六成。下面是一个简单的 TTL 缓存实现小项目可以直接抄。import json import sqlite3 import time class TtlCache: def __init__(self, pathserp_cache.db, ttl3600): self.conn sqlite3.connect(path) self.ttl ttl self.conn.execute( CREATE TABLE IF NOT EXISTS cache (key TEXT PRIMARY KEY, data TEXT, ts INTEGER) ) def get(self, key): row self.conn.execute( SELECT data, ts FROM cache WHERE key ?, (key,) ).fetchone() if row and time.time() - row[1] self.ttl: return json.loads(row[0]) return None def set(self, key, data): self.conn.execute( INSERT OR REPLACE INTO cache VALUES (?, ?, ?), (key, json.dumps(data), int(time.time())), ) self.conn.commit()用的时候很简单发请求前先查缓存命中就直接用没命中再去调 API然后把结果写回去。TTL 怎么设要看数据时效性。排名追踪可以设 12 到 24 小时新闻和热点监控只能给 10 到 30 分钟。把 TTL 写在配置里而不是写死在代码里后面调起来方便。5. 跑批最容易踩的坑问题速查与排查实录5.1 高频问题速查表我把自己和身边朋友在跑 SERP 任务时遇到的高频问题整理成了一张表遇到问题时可以按表排查。症状可能原因处理建议HTTP 429配额用尽或并发超限查用量和并发上限加缓存降速错峰HTTP 403key 无效、IP 白名单没配、出口 IP 被服务商风控检查 key 和来源 IP补白名单联系客服返回 error / status FAILED参数不合法或服务商内部错误对照文档检查参数名重试organic 字段为空查询被判定异常命中验证码页或关键词太偏门加 gl/hl/geo 参数降频换出口 IP 环境结果和浏览器不一致出口 IP 地理信息与目标区域不符显式传 gl 参数别依赖 IP 定位生产用住宅 IP费用飙升并发过高且完全没有缓存分析调用日志找重复 query加缓存和去重大部分问题要么来自配额要么来自出口 IP 质量要么来自字段理解偏差。排查顺序建议是先看服务商后台的用量和错误日志再看自己的调用代码最后才怀疑业务逻辑。很多人一上来就怀疑代码写得不对结果查了半天发现只是套餐到期。5.2 一次真实排查日志里全是 403 的那一周说一个我自己踩过的例子。有段时间我们某个关键词监控任务的日志里 403 突然占了七成后台看配额明明还剩很多。排查思路顺着 key 状态、请求头、频率一路捋过去最后发现是服务商那边共享出口 IP 池被风控连带我们这些租户一起遭殃。这种问题在低价共享型服务里不算少见。我们的对策是三步先停掉当天任务止损把失败查询写进本地队列等风控缓解后再补跑然后在架构上加了那层 SQLite 缓存同时把高优先级关键词切到另一个服务商。那次之后我的经验是不要把生产任务完全绑在一家低价服务上至少要留一条备用通道哪怕只是几百次免费额度也能在别人故障时帮你撑过最紧急的窗口。5.3 我推荐的跑批参数和安全水位最后给一套我实际在用的跑批参数可以直接拿去做默认值。并发控制在 2 到 4不要贪多同一关键词的两次请求之间加 1 到 3 秒随机延时单个任务设置日配额告警用到 70% 就要发通知所有失败请求进重试队列而不是直接丢弃缓存 TTL 按数据场景分级。这套参数的思路很简单宁可跑得慢一点也不要因为高频请求把服务商账号或自己的出口 IP 搭进去。SERP 数据讲究的是持续稳定单次跑得快没有意义。跑批调度如果不是很复杂我建议直接用系统 crontab 加日志切割就够了没必要一开始就上重型任务调度框架等任务数量上来了再迁移也不迟。最后再分享一个实操体会。我见过太多人把 SERP API 的预算当成“买出来的”其实它是“省出来的”。先估准用量再选套餐然后把缓存做厚最后才用自建或更贵的服务补剩余短板。这样组合下来绝大多数中小规模项目一个月花几十美元就能稳定跑完所有查询需求。如果你还处在方案验证阶段甚至可以不花钱把各家免费额度用一圈再决定长期用哪家这个办法我每做一个新项目都会先用一遍。