Amazonで商品を見るセール会場へ

Figma REST APIで画像を一括書き出しする方法|node ID・倍率・Python保存

Figmaのフレームやコンポーネントを画像として書き出すREST APIは、GET /v1/images/:keyです。複数のnode IDをidsへまとめて指定し、返ってきた画像URLから別途ダウンロードします。APIの応答自体は画像ファイルではありません。

この記事は2026年10月3日に確認した公式仕様に基づき、PNGを保存するPython例を掲載します。保存処理は模擬HTTP応答で確認していますが、実際のFigma APIでのレンダリング・画像寸法の検証は未実施です。Figma公式の画像API

目次

レンダリング画像と画像塗りの取得を区別する

API取得するものURLの有効期間
GET /v1/images/:key指定したノードをPNG・JPG・SVG・PDFへレンダリングしたURL30日
GET /v1/files/:key/imagesファイル内の画像塗りに使うimageRefとダウンロードURL最大14日

画面全体やボタンをそのまま書き出したい場合は前者です。画像塗りの取得は、ノードのレイアウトや文字まで含む画面の書き出しではありません。得られた一時URLは公開サイトの恒久画像URLに使わず、必要なファイルを保存します。

PAT・ファイルキー・node IDを用意する

画像の書き出しにはfile_content:readスコープと、対象ファイルへのアクセス権が必要です。個人アクセストークンの取得を参照し、環境変数FIGMA_TOKENへ設定します。

ファイルキーはFigmaのURLの/design/や/file/の直後にある文字列です。node IDは対象フレーム・レイヤーへのリンクで確認します。URLのnode-id=1-2は、APIでは1:2として指定します。ファイル名やフレーム名だけではIDの代わりになりません。

書き出しパラメーター

項目役割
idsnode IDをカンマ区切りで指定
formatpng・jpg・svg・pdf
scale0.01〜4の倍率
version指定バージョンを使う。省略時は現行版
svg_outline_textSVGの文字をアウトラインにするか
svg_include_idSVGへレイヤー名に基づくidを含めるか
svg_include_node_idSVGへdata-node-idを含めるか
svg_simplify_stroke内側・外側の線をマスクではなくstrokeへ簡略化するか
contents_onlyノードに重なる外側の内容を含めるか
use_absolute_bounds切り抜きや空白によらずノード全体の寸法を使うか

画像は最大32メガピクセルまでで、それを超える場合は縮小されます。scale=2を指定しても、常に寸法がちょうど2倍になるとは限りません。通常のエディター書き出しは倍率と固定幅の使い方、SVGの文字はSVG設定を参照してください。

応答のimagesとnullを確認する

成功時のimagesはnode IDとURLの対応表です。statusは成功時に省略されると公式に説明されているため、常に200というフィールドがあると仮定しないでください。

{
  "images": {
    "1:2": "https://example.com/temporary-image.png",
    "3:4": null
  }
}

これは形を説明する例です。nullは、そのノードのレンダリング失敗を示します。IDが存在しない、表示可能な内容がない、不可視・透明などの条件を確認します。1件がnullでも、ほかのノードのURLを保存できる場合があります。

PythonでPNGを保存する

次をexport_images.pyとして保存します。環境変数FIGMA_FILE_KEYへファイルキー、FIGMA_NODE_IDSへ1:2,3:4のようにIDを設定します。出力先はfigma-imagesです。同じIDのPNGがある場合は成功時に置き換えます。

import os
import re
import tempfile
from pathlib import Path
from urllib.parse import urlparse

import requests


def save_png(url, destination):
    if urlparse(url).scheme != "https":
        raise ValueError("画像URLはHTTPSである必要があります")
    # ダウンロード先にFigmaトークンを渡さない。
    response = requests.get(url, timeout=60)
    if response.status_code != 200:
        raise RuntimeError(f"画像取得失敗: HTTP {response.status_code}")
    data = response.content
    if not data.startswith(b"\x89PNG\r\n\x1a\n"):
        raise ValueError("取得結果がPNGではありません")
    destination = Path(destination)
    temporary = None
    try:
        with tempfile.NamedTemporaryFile(dir=destination.parent, delete=False) as handle:
            temporary = Path(handle.name)
            handle.write(data)
        temporary.replace(destination)
    finally:
        if temporary is not None:
            temporary.unlink(missing_ok=True)


def main():
    key = os.environ["FIGMA_FILE_KEY"]
    ids = list(dict.fromkeys(x.strip().replace("-", ":")
                            for x in os.environ["FIGMA_NODE_IDS"].split(",")))
    if not re.fullmatch(r"[A-Za-z0-9_-]+", key):
        raise SystemExit("ファイルキーを確認してください")
    if not ids or any(not re.fullmatch(r"\d+:\d+", x) for x in ids):
        raise SystemExit("node IDを1:2,3:4の形式で設定してください")
    response = requests.get(
        f"https://api.figma.com/v1/images/{key}",
        headers={"X-Figma-Token": os.environ["FIGMA_TOKEN"]},
        params={"ids": ",".join(ids), "format": "png", "scale": 2}, timeout=60
    )
    if response.status_code == 429:
        raise SystemExit("API制限に達しました。Retry-Afterを確認してください")
    if response.status_code != 200:
        raise SystemExit(f"レンダリング要求失敗: HTTP {response.status_code}")
    result = response.json()
    if result.get("err"):
        raise SystemExit("APIがレンダリングエラーを返しました")
    images = result["images"]
    directory = Path("figma-images")
    directory.mkdir(exist_ok=True)
    for node_id in ids:
        url = images.get(node_id)
        if not url:
            print(node_id, "レンダリング結果なし")
            continue
        try:
            save_png(url, directory / (node_id.replace(":", "-") + ".png"))
        except (requests.RequestException, OSError, ValueError, RuntimeError):
            print(node_id, "保存失敗。HTTP結果・接続・出力先を確認してください")
        else:
            print(node_id, "保存しました")


if __name__ == "__main__":
    main()
python -m pip install requests
python export_images.py

APIへの認証ヘッダーと、画像URLからの取得を分けています。PNGのシグネチャを確認するので、エラーページをPNG名で保存することを避けられます。ただし、この確認だけでは画像が最後まで正常か、期待するピクセル寸法かは判定できません。保存後に実ファイルを開いて確認してください。

403・404・429と保存失敗を切り分ける

状況確認すること
API要求が403PATの期限・スコープ、対象ファイルへの権限
API要求が404ファイルキーとアクセス対象
API要求が429Retry-After、席と対象リソースのプラン、連続呼び出し
imagesの値がnullnode ID、不可視・透明・描画対象なし
画像URLから取得できないURLの期限、通信、HTTP結果
保存できない出力先の権限、同名ファイルを別アプリが使用していないか

画像レンダリングはTier 1です。idsをまとめることでAPI要求数を減らせますが、画像のダウンロードまで含めて1要求になるわけではありません。REST APIの制限

大きなファイルでは対象を絞り、成功分・null・保存失敗を記録して再取得範囲を決めます。API全体の役割はREST APIとPlugin APIの比較で説明しています。

サービス

Service

デザイン制作に関心がありましたら、ぜひ詳細をご覧ください。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

Figmaのおすすめ書籍

Figma用PCの選び方

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次