API 文件
基底 URL 為 https://yhfdghkh6544.com/v1。所有端點皆使用標準 HTTP,參數可放在查詢字串(GET)或 JSON 本文(POST)中。
快速開始
- 免費註冊,並在控制台的「API Key」頁面建立 Key。
- 將 Key 放入
X-Access-Key請求標頭,呼叫截圖端點:
curl "https://yhfdghkh6544.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $SNAPI_KEY" \
-o screenshot.png身分驗證
每個請求都需要 API Key,可透過以下任一方式傳遞:
- 請求標頭
X-Access-Key: snp_…(建議使用,適合伺服器端呼叫) - 查詢參數
access_key=snp_… - 簽章 URL(需將網址放入網頁時使用,不會洩露 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 回傳檔案網址與中繼資料。 |
擷取單頁應用程式(React、Vue 等):頁面會在真實瀏覽器中執行完 JavaScript 後再截圖。預設的 networkidle 會等待頁面取得資料;若內容是在請求結束後才透過計時器或動畫算繪,請加上 wait_for_selector,指定代表「內容已就緒」的元素;若沒有合適的元素,再用 delay 多等一會。
PDF 端點
/v1/pdf/v1/pdf每次產生 PDF 會扣除 2 次額度。列印前會先捲動整個頁面,以觸發延遲載入的內容。除共用參數外,也支援:
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
| paper | enum | a4 | 紙張:a4 或 letter。頁面自帶 @page 規則時,優先使用頁面設定。 |
| print_background | boolean | true | 列印背景色與背景圖片。 |
| pdf_media | enum | print 使用列印樣式;screen 使用螢幕樣式(所見即所得)。 |
curl -X POST "https://yhfdghkh6544.com/v1/pdf" \
-H "X-Access-Key: $SNAPI_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-Snapi-Cache:HIT或MISSX-Snapi-Truncated: true:整頁高度超過 20,000 像素,已截斷X-Snapi-Format-Changed: webp:PNG 超過 5 MB 時自動轉為 WebP(明確指定 format=png 時不會轉換)
設定 response_type=json 時,會回傳檔案網址與中繼資料:
curl -X POST "https://yhfdghkh6544.com/v1/screenshot" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "response_type": "json"}'
# 回傳
{
"url": "https://yhfdghkh6544.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?請在自己的伺服器端,使用 Key 對應的 secret 計算簽章(可在控制台的 API Key 頁面查看 secret):
canonical = 將 signature 以外的所有參數,依參數名稱的字典順序排序,
每項格式為 k=urlencode(v)(RFC 3986,空格編碼為 %20),並以 & 串接
signature = hex(HMAC-SHA256(secret, canonical))簽章正確即視為通過身分驗證。任何參數遭到變更(例如更換 url),簽章都會失效。選填參數 expires(Unix 秒)也會參與簽章計算,過期後回傳 signature_expired。若要重新整理快取,只要變更一個不影響功能的參數(如 v=2)並重新簽章即可。簽章 URL 僅支援 GET。
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, accessKey, secret) {
const all = { ...params, access_key: accessKey };
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://yhfdghkh6544.com/v1/screenshot?${canonical}&signature=${signature}`;
}
const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY, SECRET);
// <img src={src} alt="網頁預覽" />快取
參數完全相同的請求會命中快取(省略參數與明確傳入預設值視為相同;驗證參數與快取參數不納入比較)。命中時,二進位模式會回傳 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 次 | 否 |
| 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。 |
| webhook_url | string | — | 選填。全部完成後接收通知的網址,請參閱「完成回呼」。 |
curl -X POST "https://yhfdghkh6544.com/v1/batch" \
-H "X-Access-Key: $SNAPI_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/snapi"
}'
# 回傳 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/snapi", "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://yhfdghkh6544.com/v1/batch/bat_01j…" -H "X-Access-Key: $SNAPI_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://yhfdghkh6544.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-Snapi-Signature: t=1760779812,v1=5d3f…:t為傳送時間(Unix 秒),v1為簽章X-Snapi-Event: batch.completed、X-Snapi-Delivery-Attempt: 1(第幾次傳送)
v1 = hex(HMAC-SHA256(secret, t + "." + 原始請求本文))
secret 是提交任務時使用的 API Key 所對應的簽章密鑰(可在控制台的 API Key 頁面查看)- 請在 10 秒內回傳 2xx,否則視為失敗。失敗後會在 10 秒、1 分鐘、5 分鐘後各重試一次(總計最多 4 次)。
- 極少數情況下,同一個任務可能會收到重複通知,請依
batch.id排除重複通知。 - 驗證簽章時,請使用收到的原始位元組計算,並確認
t與目前時間相差不超過幾分鐘,以防止重放攻擊。 - 回呼網址必須是可從公網存取的 http(s) 網址,不得指向內部網路。
import crypto from "node:crypto";
// rawBody 必須是收到的原始位元組,不可先 JSON.parse 再序列化
function verifySnapiWebhook(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);
}
// verifySnapiWebhook(req.rawBody, req.headers["x-snapi-signature"], SNAPI_SECRET)用量查詢
/v1/usagecurl "https://yhfdghkh6544.com/v1/usage" -H "X-Access-Key: $SNAPI_KEY"
{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }健康檢查
/v1/health無須驗證身分,回傳節點狀態與瀏覽器集區狀態(總數、忙碌、閒置)。