API 文档
基础地址 https://glanceshot.com/v1。所有接口都是标准 HTTP,参数可以放在查询串(GET)或 JSON body(POST)里。
快速开始
- 免费注册,在控制台的「API Key」页面创建一个 Key。
- 把 Key 放进
X-Access-Key请求头,调用截图接口:
curl "https://glanceshot.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-o screenshot.png鉴权
每个请求都需要 API Key,可以用下面任一方式传递:
- 请求头
X-Access-Key: gls_…(推荐,服务端调用使用) - 查询参数
access_key=gls_…(只在服务端调用时使用,不要写进网页) - 签名 URL(需要把地址放进网页时使用,API Key 和 secret 都不会暴露)
API Key 的明文只在创建时显示一次,请妥善保存。泄露后可以在控制台停用。
截图接口
/v1/screenshot/v1/screenshot截图专用参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| format | enum | png | png、jpeg 或 webp。 |
| device_scale_factor | number | 1 | 缩放比 1–3。设为 2 可获得 Retina 清晰度,体积约为 4 倍。 |
| quality | integer | 80 | JPEG / WebP 质量,1–100。 |
| full_page | boolean | false | 截取整页。会逐屏滚动触发懒加载,高度上限 20,000 像素。 |
| selector | string | — | 只截取匹配该 CSS 选择器的第一个元素。不能与 full_page 同时使用。 |
截图和 PDF 共用的参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| url | string | — | 要截取的网页地址,http 或 https。与 html 二选一。网址里的 #片段会保留,hash 路由的单页应用(如 https://app.com/#/report/1)可以直接截取对应页面。 |
| html | string | — | 直接传入 HTML(最大 2 MB),仅支持 POST。 |
| viewport_width | integer | 1280 | 视口宽度,320–3840。小于 768 时按移动设备渲染。 |
| viewport_height | integer | 800 | 视口高度,200–3840。 |
| wait_until | enum | networkidle | 等待策略:domcontentloaded(最快,适合静态页)、load、networkidle(从打开页面起跟踪所有请求,页面加载完后连续 500 毫秒没有进行中的请求才截图,最多再等 8 秒,适合单页应用)。 |
| wait_for_selector | string | — | 页面加载完后,等匹配这个 CSS 选择器的元素出现并且可见再截图,最多等 10 秒;等不到返回 selector_not_found(不计费)。适合不靠网络请求、用定时器或动画延迟渲染内容的单页应用,例如 .chart-ready。 |
| delay | integer | 0 | 等待完成后再延迟的毫秒数,0–10000。用于等动画或懒加载组件。 |
| block_ads | boolean | true | 拦截广告与跟踪域名的请求,并隐藏页面上的广告位。 |
| block_cookie_banners | boolean | true | 隐藏 Cookie 同意弹窗。 |
| dark_mode | boolean | false | 模拟 prefers-color-scheme: dark。 |
| hide_selectors | string | — | 要隐藏的元素,CSS 选择器列表,例如 .ad,#popup。 |
| cache | boolean | true | 是否查找缓存。设为 false 时强制重新渲染,结果仍会写入缓存。 |
| cache_ttl | integer | 86400 | 缓存有效期(秒),60–2592000。 |
| response_type | enum | binary | binary 直接返回文件;json 返回文件地址和元数据。 |
| proxy | string | — | 可选,用你自己购买的代理访问目标网页(代理费用由你承担),例如需要从指定国家或地区访问时。支持 socks5:// 和 http://,可以带账号密码,格式如 socks5://user:pass@203.0.113.10:1080。只能放在 POST 请求体里,不能用于 GET 请求、签名 URL 和批量任务。用了代理的请求单独缓存;代理连不上、认证失败或无法访问目标网站时返回 proxy_failed,不计费。 |
| cookies | string | object[] | — | 目标网站的 Cookie,可以是 sid=abc; theme=dark 这样的一行,也可以是 [{"name":"sid","value":"abc"}] 这样的数组(可带 domain、path)。只会发给目标网站,不发给页面里的第三方。 |
| headers | object | — | 要附加的请求头,如 Authorization: Bearer …。只发给目标网站;浏览器自己管理的头(Host、Cookie、User-Agent 等)不能设。 |
| local_storage | object | — | 要写入目标网址所在源的 localStorage,键值都是字符串。 |
| session_storage | object | — | 同 local_storage,写入 sessionStorage。 |
| login_profile | string | — | 用浏览器插件保存的登录档案编号(lp_8f2c…)。比直接传 cookies 更省事,也能用在批量任务里(任务里不保存任何凭据)。 |
截取单页应用(React、Vue 等):页面会在真实浏览器里执行完 JavaScript 再截图。默认的 networkidle 会等页面拉完数据;如果内容是请求结束后再用定时器或动画渲染的,加上 wait_for_selector 指定一个“内容已就绪”的元素;实在没有合适的元素,再用 delay 多等一会儿。
PDF 接口
/v1/pdf/v1/pdfPDF 每次计 2 次额度。打印前会先滚动一遍页面触发懒加载内容。除共用参数外,还支持:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| paper | enum | a4 | 纸张:a4 或 letter。页面自带 @page 规则时优先使用页面的设置。 |
| print_background | boolean | true | 打印背景色和背景图。 |
| pdf_media | enum | print 使用打印样式;screen 使用屏幕样式(所见即所得)。 |
curl -X POST "https://glanceshot.com/v1/pdf" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>季度报告</h1><p>正文……</p>", "paper": "a4"}' \
-o report.pdf返回结果
默认(response_type=binary)直接返回文件,Content-Type 为对应格式。响应头:
X-Request-Id:本次请求 ID,排查问题时请提供X-Glanceshot-Cache:HIT或MISSX-Glanceshot-Truncated: true:整页超过 20,000 像素被截断X-Glanceshot-Format-Changed: webp:PNG 超过 5 MB 自动转为 WebP(显式指定 format=png 时不会转换)
设置 response_type=json 时返回文件地址和元数据:
curl -X POST "https://glanceshot.com/v1/screenshot" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "response_type": "json"}'
# 返回
{
"url": "https://glanceshot.com/i/3f/3f9c….png",
"cache_hit": false,
"duration_ms": 1284,
"format": "png",
"width": 1280,
"height": 800,
"request_id": "req_01j…"
}签名 URL
想把截图地址直接写进 <img src>,又不想暴露 API Key?签名 URL 里不放 API Key,只放公开的 key_id,再在你自己的服务端用 Key 对应的 secret 计算签名。Key ID 和 secret 都在控制台的 API Key 页面查看:
canonical = 除 signature 外的全部参数,按参数名字典序排序,
每项 k=urlencode(v)(RFC 3986,空格编码为 %20),用 & 连接
signature = hex(HMAC-SHA256(secret, canonical))签名正确即视为已鉴权,缺少签名或签名不对都会被拒绝。任何参数被改动(比如换了 url),签名都会失效。可选参数 expires(Unix 秒)参与签名,过期后返回 signature_expired。想刷新缓存时,改一个无意义的参数(如 v=2)重新签名即可。签名 URL 只支持 GET 方式调用截图和 PDF 接口,也不能带代理参数。
key_id 是公开的,单独拿到它不能调用接口。不要把 API Key(access_key)放进签名 URL,带了会直接返回 invalid_params。如果之前把 API Key 写进过网页,请在控制台停用这把 Key,再新建一把。
import crypto from "node:crypto";
// RFC 3986 编码(空格为 %20),必须和服务端规则一致
const enc = (v) =>
encodeURIComponent(v).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
function signedUrl(params, keyId, secret) {
const all = { ...params, key_id: keyId };
const canonical = Object.keys(all).sort().map((k) => `${k}=${enc(String(all[k]))}`).join("&");
const signature = crypto.createHmac("sha256", secret).update(canonical).digest("hex");
return `https://glanceshot.com/v1/screenshot?${canonical}&signature=${signature}`;
}
const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY_ID, SECRET);
// <img src={src} alt="网页预览" />使用代理
需要从指定国家或地区访问网页时(例如查看当地的语言、内容和价格),可以在请求里带上你自己购买的代理,代理费用由你承担。页面和页面上的图片、脚本、接口请求都会经这个代理加载。支持 socks5:// 和 http:// 两种代理,可以带用户名和密码。
curl -X POST "https://glanceshot.com/v1/screenshot" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "proxy": "socks5://user:pass@203.0.113.10:1080"}' \
-o screenshot.pngproxy只能放在 POST 请求体里:GET 请求、签名 URL 和批量任务都不能带,避免代理的账号密码出现在网址、浏览器历史或网页里。- 用户名或密码里有
@、:等特殊字符时,要先做 URL 编码(例如@写成%40)。 - 用了代理的请求单独缓存,不会和不带代理、或带其他代理的请求共用结果。
- 代理连不上、认证失败或无法访问目标网站时返回
proxy_failed,不计费,message说明具体原因。 - 代理必须是公网地址。目标网址的限制和不带代理时一样,不能访问内网地址。
- 经代理访问网站时,请遵守目标网站的使用条款和当地法律。
截登录后的页面
要截取需要登录才能看到的页面,可以带上你自己账号的登录状态。有两种方式:直接在请求里传 cookies、headers、local_storage、session_storage,或者用 Glanceshot 浏览器插件把登录状态保存成“登录档案”、请求里只放 login_profile。
curl -X POST "https://glanceshot.com/v1/screenshot" -H "X-Access-Key: $GLANCESHOT_KEY" -H "Content-Type: application/json" -d '{
"url": "https://app.example.com/dashboard",
"cookies": "sid=YOUR_SESSION; theme=dark",
"local_storage": {"token": "YOUR_TOKEN"}
}' -o screenshot.png- 插件能读出网页脚本读不到的登录凭据(包括 HttpOnly Cookie),以及 localStorage、IndexedDB,适合大多数网站。到控制台的“登录档案”页安装并连接插件。
- 登录状态只能通过 POST 请求体传(
GET、签名 URL 都会被拒绝),不会写进日志和调用记录;带了登录状态的请求按它单独缓存,不会和别人共享。 - 如果带了登录状态、页面却跳回了登录页,返回
login_expired、不计费(说明登录已失效,用插件重新同步)。 - 对于会话绑定了设备或 IP、无法在云端重现登录的网站(如网银),用插件的“截取当前页面”在你自己的浏览器里截图后上传。
缓存
参数完全相同的请求会命中缓存(省略参数和显式传默认值视为相同;鉴权参数和缓存参数不参与比较)。命中时二进制模式返回 302 跳转到文件地址,并带 Cache-Control,浏览器会自动跟随跳转并缓存;JSON 模式返回 cache_hit: true。
命中缓存不计费。同一参数的并发请求只会渲染一次。
限额与计费
- 只对成功(2xx)且未命中缓存的请求计费:截图 1 次,PDF 2 次。
- 超时、渲染失败、目标站报错或拦截访问、参数错误、鉴权失败都不扣额度。
- 额度按自然月(UTC)重置。免费套餐每月 100 次,用完后返回 quota_exceeded。
- 超过每秒请求数或并发数返回 429,响应头 Retry-After 给出建议的等待秒数。
- 单次渲染最长 30 秒;单页下载量上限 50 MB;输出文件上限 50 MB。
查看各套餐的具体限额:价格。
错误码
错误响应统一为 JSON:
{
"error": {
"code": "render_failed",
"message": "target responded with an error status",
"upstream_status": 404,
"request_id": "req_01j…"
}
}| HTTP | code | 含义 | 计费 |
|---|---|---|---|
| 400 | invalid_params | 参数缺失或超出范围,message 说明具体是哪个参数 | 否 |
| 400 | html_too_large | html 超过 2 MB | 否 |
| 401 | unauthorized | 缺少 API Key,或 Key 无效 / 已停用 | 否 |
| 401 | signature_invalid | 签名不匹配(参数被改动或 secret 错误) | 否 |
| 401 | signature_expired | 签名 URL 已超过 expires 时间 | 否 |
| 403 | url_blocked | 目标地址不允许访问(例如内网地址、localhost) | 否 |
| 408 | render_timeout | 渲染超过 30 秒 | 否 |
| 422 | render_failed | 目标站返回 4xx/5xx、DNS 失败或证书错误;带 upstream_status | 否 |
| 422 | selector_not_found | selector 没有匹配到元素,或 wait_for_selector 等待超时 | 否 |
| 422 | too_many_redirects | 重定向超过 5 次 | 否 |
| 422 | site_blocked | 目标网站没有显示正常内容,而是显示了人机验证、验证码、登录墙或拒绝访问的页面;不计费 | 否 |
| 422 | login_expired | 带了登录状态,但目标网站显示的还是登录页,说明登录状态已失效。 | 否 |
| 422 | proxy_failed | 你传入的代理连不上、认证失败,或代理无法访问目标网站;message 说明具体原因,不计费 | 否 |
| 429 | rate_limited | 超过每秒请求数,按 Retry-After 重试 | 否 |
| 429 | concurrency_exceeded | 超过并发数 | 否 |
| 429 | quota_exceeded | 当月额度已用完(免费套餐) | 否 |
| 429 | too_many_batches | 同时未完成的批量任务超过 5 个 | 否 |
| 500 | internal | 服务端错误,请带上 request_id 联系我们 | 否 |
异步批量
/v1/batch/v1/batch/{id}一次提交 1–100 个网址,接口立即返回任务 ID(HTTP 202),截图在后台逐个完成。适合批量截图、不想一直等待连接的场景。可以轮询查询接口,也可以填 webhook_url,全部完成后我们会主动通知你。鉴权方式和同步接口相同(只支持请求头或 access_key 参数,不支持签名 URL)。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| type | enum | screenshot | screenshot(截图)或 pdf。 |
| urls | string[] | — | 要处理的网址,1–100 个。任何一个不合法时整个请求返回 400,message 指出是第几个。 |
| options | object | {} | 所有网址共用的参数,和同步接口的参数相同(如 full_page、format、viewport_width、cache_ttl),不能包含 url、html、response_type、proxy。 |
| webhook_url | string | — | 可选。全部完成后通知的地址,见「完成回调」。 |
curl -X POST "https://glanceshot.com/v1/batch" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "screenshot",
"urls": ["https://example.com", "https://example.org"],
"options": { "full_page": true, "format": "webp" },
"webhook_url": "https://your-app.com/hooks/glanceshot"
}'
# 返回 202
{
"id": "bat_01j…",
"type": "screenshot",
"status": "queued",
"total": 2, "succeeded": 0, "failed": 0,
"created_at": "2026-10-18T09:30:00Z", "completed_at": null,
"webhook": { "url": "https://your-app.com/hooks/glanceshot", "status": "none", "attempts": 0 },
"items": [
{ "index": 0, "url": "https://example.com", "status": "pending", "result": null, "error": null },
{ "index": 1, "url": "https://example.org", "status": "pending", "result": null, "error": null }
]
}查询进度:任务状态 status 依次是 queued(排队中)、running(处理中)、completed(全部完成,无论成功还是失败)。每个网址的状态是 pending、running、succeeded 或 failed;成功的在 result 里给出文件地址,失败的在 error 里给出错误码(和同步接口的错误码一致)。
curl "https://glanceshot.com/v1/batch/bat_01j…" -H "X-Access-Key: $GLANCESHOT_KEY"
{
"id": "bat_01j…",
"status": "completed",
"total": 2, "succeeded": 1, "failed": 1,
"completed_at": "2026-10-18T09:30:12Z",
"items": [
{
"index": 0, "url": "https://example.com", "status": "succeeded", "duration_ms": 1830,
"result": { "url": "https://glanceshot.com/i/3f/3f9c….webp", "mime": "image/webp", "width": 1280, "height": 2410, "cache_hit": false },
"error": null
},
{
"index": 1, "url": "https://example.org", "status": "failed", "duration_ms": 640,
"result": null,
"error": { "code": "render_failed", "message": "target responded with an error status" }
}
]
}- 计费规则和同步接口相同:每个成功的网址截图计 1 次、PDF 计 2 次,命中缓存和失败的不扣额度。
- 提交时额度已经用完会直接返回
quota_exceeded;处理过程中额度用完,剩下的网址会以quota_exceeded失败。 - 每个账号同时最多 5 个未完成的批量任务,超过返回
too_many_batches。 - 结果文件的有效期由
options.cache_ttl决定(默认 1 天),请及时下载保存。 - 查询结果和回调里的
webhook.url只显示到路径,不回显查询串。
完成回调
填了 webhook_url 时,任务全部完成后我们会向它发送一个 POST,请求体是 JSON:{ "event": "batch.completed", "batch": { … } },其中 batch 和查询接口的返回完全相同。请求头:
X-Glanceshot-Signature: t=1760779812,v1=5d3f…:t是发送时间(Unix 秒),v1是签名X-Glanceshot-Event: batch.completed、X-Glanceshot-Delivery-Attempt: 1(第几次投递)
v1 = hex(HMAC-SHA256(secret, t + "." + 原始请求体))
secret 是提交任务时所用 API Key 对应的签名 secret(控制台 API Key 页面查看)- 请在 10 秒内返回 2xx,否则视为失败。失败后会在 10 秒、1 分钟、5 分钟后各重试一次(共最多 4 次)。
- 极少数情况下同一个任务可能收到重复通知,请按
batch.id去重。 - 验签时用收到的原始字节计算,并检查
t与当前时间相差不超过几分钟,防止重放。 - 回调地址必须是公网可访问的 http(s) 地址,不能指向内网。
import crypto from "node:crypto";
// rawBody 必须是收到的原始字节,不能先 JSON.parse 再序列化
function verifyGlanceshotWebhook(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; // 防重放
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const got = Buffer.from(parts.v1 ?? "");
return got.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), got);
}
// verifyGlanceshotWebhook(req.rawBody, req.headers["x-glanceshot-signature"], GLANCESHOT_SECRET)用量查询
/v1/usagecurl "https://glanceshot.com/v1/usage" -H "X-Access-Key: $GLANCESHOT_KEY"
{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }健康检查
/v1/health无需鉴权,返回节点状态和浏览器池状态(总数、忙碌、空闲)。