Snapi
開発者向けドキュメント

API ドキュメント

ベース URL は https://yhfdghkh6544.com/v1 です。すべての API は標準の HTTP を使用し、パラメータはクエリ文字列(GET)または JSON ボディ(POST)で渡せます。

クイックスタート

  1. 無料で登録し、コンソールの「API Key」ページでキーを作成します。
  2. X-Access-Key リクエストヘッダーにキーを設定し、スクリーンショット API を呼び出します。
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(URL をウェブページに埋め込む場合に使用します。シークレットは公開されません)

API Key の値が表示されるのは作成時の一度だけです。安全な場所に保管してください。漏えいした場合はコンソールで無効化できます。

スクリーンショット API

GET/v1/screenshot
POST/v1/screenshot

スクリーンショット専用のパラメータ:

パラメータ型デフォルト説明
formatenumpngpng、jpeg、webp のいずれかです。
device_scale_factornumber1スケール倍率です。1–3。2 にすると Retina 相当の解像度になり、ファイルサイズは約 4 倍になります。
qualityinteger80JPEG / WebP の画質です。1–100。
full_pagebooleanfalseページ全体を撮影します。画面単位でスクロールして遅延読み込みを実行します。高さの上限は 20,000 ピクセルです。
selectorstring—この CSS セレクタに最初に一致する要素だけを撮影します。full_page とは併用できません。

スクリーンショットと PDF に共通のパラメータ:

パラメータ型デフォルト説明
urlstring—撮影するページの URL です。http または https を指定します。html とのいずれか一方を指定してください。URL の # フラグメントは保持されるため、ハッシュルーティングを使うシングルページアプリ(例:https://app.com/#/report/1)も該当ページを直接撮影できます。
htmlstring—HTML を直接渡します(最大 2 MB)。POST のみ対応しています。
viewport_widthinteger1280ビューポートの幅です。320–3840。768 未満の場合はモバイル端末としてレンダリングします。
viewport_heightinteger800ビューポートの高さです。200–3840。
wait_untilenumnetworkidle待機方法です。domcontentloaded(最速、静的ページ向け)、load、networkidle(ページを開いた時点からすべてのリクエストを追跡し、ページの読み込み完了後、処理中のリクエストがない状態が 500 ミリ秒続くと撮影します。追加の待機は最大 8 秒で、シングルページアプリ向けです)。
wait_for_selectorstring—ページの読み込み完了後、この CSS セレクタに一致する要素が表示されるまで最大 10 秒待機してから撮影します。表示されない場合は selector_not_found を返します(課金対象外)。.chart-ready など、ネットワークリクエストではなくタイマーやアニメーションでコンテンツを遅延表示するシングルページアプリに適しています。
delayinteger0待機完了後に追加で待つ時間です。0–10000 ミリ秒。アニメーションや遅延読み込みの完了を待つ場合に使います。
block_adsbooleantrue広告・トラッキングドメインへのリクエストをブロックします。
block_cookie_bannersbooleantrueCookie 同意バナーを非表示にします。
dark_modebooleanfalseprefers-color-scheme: dark をエミュレートします。
hide_selectorsstring—非表示にする要素の CSS セレクタのリストです。例:.ad,#popup。
cachebooleantrueキャッシュを参照するかどうかを指定します。false にすると強制的に再レンダリングしますが、結果はキャッシュに保存されます。
cache_ttlinteger86400キャッシュの有効期間(秒)です。60–2592000。
response_typeenumbinarybinary はファイルを直接返し、json はファイルの URL とメタデータを返します。

シングルページアプリ(React、Vue など)の撮影:実際のブラウザーで JavaScript を実行してから撮影します。デフォルトの networkidle はページのデータ取得完了を待ちます。リクエスト終了後にタイマーやアニメーションでコンテンツが表示される場合は、wait_for_selector で「コンテンツの準備完了」を示す要素を指定してください。適切な要素がない場合は、delay で待機時間を追加できます。

PDF API

GET/v1/pdf
POST/v1/pdf

PDF は 1 回の生成で 2 回分の利用枠を消費します。印刷前にページ全体を一度スクロールして、遅延読み込みを実行します。共通パラメータに加え、次のパラメータに対応しています。

パラメータ型デフォルト説明
paperenuma4用紙サイズです。a4 または letter。ページに @page ルールがある場合は、ページ側の設定を優先します。
print_backgroundbooleantrue背景色と背景画像を印刷します。
pdf_mediaenumprintprint は印刷用スタイル、screen は画面用スタイル(画面表示どおり)を使用します。
HTML から PDF に変換
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 または MISS
  • X-Snapi-Truncated: true:ページ全体が 20,000 ピクセルを超えたため切り詰められたことを示します
  • X-Snapi-Format-Changed: webp:PNG が 5 MB を超えたため WebP に自動変換されたことを示します(format=png を明示的に指定した場合は変換しません)

response_type=json を設定すると、ファイルの URL とメタデータを返します。

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

API Key を公開せずに、スクリーンショットの URL を <img src> に直接指定したい場合は、ご自身のサーバーでキーに対応するシークレットを使って署名を生成してください(シークレットはコンソールの「API Key」ページで確認できます)。

署名ルール
canonical = signature を除くすべてのパラメータを名前の辞書順に並べ、
            各項目を k=urlencode(v)(RFC 3986、スペースは %20 にエンコード)の形式にして、& で連結します
signature = hex(HMAC-SHA256(secret, canonical))

署名が正しければ認証済みとみなされます。パラメータが 1 つでも変更されると(例: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 でファイルの URL にリダイレクトし、Cache-Control を付与します。ブラウザーは自動的にリダイレクト先にアクセスしてキャッシュします。JSON モードでは cache_hit: true を返します。

キャッシュにヒットした場合は課金されません。同じパラメータのリクエストが同時に送信された場合、レンダリングは 1 回だけ実行されます。

利用上限と課金

  • 成功(2xx)し、キャッシュにヒットしなかったリクエストのみ課金対象です。スクリーンショットは 1 回分、PDF は 2 回分の利用枠を消費します。
  • タイムアウト、レンダリング失敗、対象サイトのエラー、パラメータエラー、認証失敗では利用枠を消費しません。
  • 利用枠は毎月 1 日(UTC)にリセットされます。無料プランは月 100 回まで利用でき、使い切ると quota_exceeded を返します。
  • 毎秒のリクエスト数または同時実行数の上限を超えると 429 を返します。レスポンスヘッダー Retry-After に推奨待機時間(秒)が示されます。
  • 1 回のレンダリングは最長 30 秒、1 ページのダウンロード量は最大 50 MB、出力ファイルは最大 50 MB です。

各プランの詳しい上限は料金ページをご覧ください。

エラーコード

エラーレスポンスはすべて JSON 形式です。

エラー形式
{
  "error": {
    "code": "render_failed",
    "message": "target responded with an error status",
    "upstream_status": 404,
    "request_id": "req_01j…"
  }
}
HTTPcode意味課金対象
400invalid_paramsパラメータが未指定、または範囲外です。message に該当するパラメータが示されますいいえ
400html_too_largehtml が 2 MB を超えていますいいえ
401unauthorizedAPI Key が未指定、無効、または無効化されていますいいえ
401signature_invalid署名が一致しません(パラメータの変更、またはシークレットの誤り)いいえ
401signature_expired署名付き URL の有効期限 expires を過ぎていますいいえ
403url_blocked対象 URL へのアクセスは許可されていません(内部ネットワークのアドレス、localhost など)いいえ
408render_timeoutレンダリングが 30 秒を超えましたいいえ
422render_failed対象サイトが 4xx/5xx を返したか、DNS または証明書のエラーが発生しました。upstream_status が付与されますいいえ
422selector_not_foundselector に一致する要素がないか、wait_for_selector の待機がタイムアウトしましたいいえ
422too_many_redirectsリダイレクトが 5 回を超えましたいいえ
429rate_limited毎秒のリクエスト数の上限を超えました。Retry-After に従って再試行してくださいいいえ
429concurrency_exceeded同時実行数の上限を超えましたいいえ
429quota_exceeded今月の利用枠を使い切りました(無料プラン)いいえ
429too_many_batches未完了のバッチジョブが同時に 5 件を超えていますいいえ
500internalサーバーエラーです。request_id を添えてお問い合わせくださいいいえ

非同期バッチ処理

POST/v1/batch
GET/v1/batch/{id}

1–100 件の URL を一度に送信すると、API はすぐにジョブ ID(HTTP 202)を返し、バックグラウンドで順番に撮影します。大量のページを撮影する場合や、接続を維持して待ちたくない場合に適しています。ステータス取得 API をポーリングするか、webhook_url を指定して、すべての処理が完了した際に通知を受け取れます。認証方法は同期 API と同じです(リクエストヘッダーまたは access_key パラメータのみ対応し、署名付き URL は使用できません)。

パラメータ型デフォルト説明
typeenumscreenshotscreenshot(スクリーンショット)または pdf です。
urlsstring[]—処理する URL です。1–100 件。1 件でも無効な URL があるとリクエスト全体が 400 を返し、message に何番目の URL かが示されます。
optionsobject{}すべての URL に共通で適用するパラメータです。同期 API と同じパラメータ(full_page、format、viewport_width、cache_ttl など)を指定できますが、url、html、response_type は含められません。
webhook_urlstring—省略可能です。すべての処理が完了した際の通知先 URL です。「完了通知」をご覧ください。
バッチジョブの送信
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(成功・失敗を問わずすべて完了)の順に変わります。各 URL の状態は pending、running、succeeded、failed のいずれかです。成功時は result にファイルの URL、失敗時は error にエラーコード(同期 API と共通)が含まれます。

バッチジョブの取得
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" }
    }
  ]
}
  • 課金ルールは同期 API と同じです。成功した URL ごとに、スクリーンショットは 1 回分、PDF は 2 回分の利用枠を消費します。キャッシュへのヒットや失敗では利用枠を消費しません。
  • 送信時に利用枠を使い切っている場合は、即座に quota_exceeded を返します。処理中に利用枠を使い切ると、残りの URL は quota_exceeded で失敗します。
  • アカウントごとに、未完了のバッチジョブは同時に最大 5 件までです。上限を超えると too_many_batches を返します。
  • 結果ファイルの有効期間は options.cache_ttl で決まります(デフォルトは 1 日)。期限内にダウンロードして保存してください。
  • 取得結果とコールバック内の webhook.url はパスまでしか表示されず、クエリ文字列は含まれません。

完了通知

webhook_url を指定すると、ジョブのすべての処理が完了した後に、その URL へ POST を送信します。リクエストボディは JSON 形式の { "event": "batch.completed", "batch": { … } } で、batch の内容はステータス取得 API のレスポンスと同一です。リクエストヘッダー:

  • 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 分後にそれぞれ 1 回再試行します(初回を含め最大 4 回)。
  • ごくまれに、同じタスクの通知が重複して届くことがあります。batch.id を使って重複を排除してください。
  • 署名の検証には、受信した生のバイト列を使用してください。また、リプレイ攻撃を防ぐため、t と現在時刻の差が数分以内であることを確認してください。
  • コールバック先には、インターネットからアクセスできる http(s) の URL を指定してください。内部ネットワークのアドレスは指定できません。
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)

使用量の確認

GET/v1/usage
shell
curl "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", ... }

ヘルスチェック

GET/v1/health

認証は不要です。ノードの状態とブラウザープールの状態(総数、使用中、空き)を返します。