Markdown to Image API 入門:cURL・Node.js・Python・n8n で PNG を生成
画像を一枚だけ書き出すなら手作業でも十分です。しかし、AI レポート、更新履歴、サポート回答、SNS 投稿を毎回同じ品質のビジュアルに変換する製品では、手動操作がすぐにボトルネックになります。Markdown to Image API を使えば、レンダリングをコードに組み込めます。Markdown を送り、形式とテーマを選び、URL またはバイナリを受け取り、必要な保存先へ送る流れです。
この記事では、MarkdownToImage API を実際に動かします。まず cURL で確認し、同じ処理を Node.js と Python で実装し、n8n を設定します。さらに、短いクイックスタートでは省かれがちな本番運用の対策も追加します。
エンドポイントと制限は、2026 年 8 月 2 日に公式 API ドキュメントで確認しました。クォータやプランは変更される可能性があるため、本番費用を見積もる前に最新の料金ページを確認してください。
画像生成が単発のデザイン作業ではなく、繰り返し実行するワークフローの一部なら API が向いています。代表的な用途は次のとおりです。
- LLM の回答をダウンロード可能なレポート画像にする;
- デプロイ後にリリースノートのカードを自動生成する;
- CMS のフィールドから Open Graph 画像や SNS カードを作る;
- コード、表、Mermaid 図、KaTeX 数式を一定の見た目で描画する;
- n8n、Dify、Make、CI、社内ツールの中で画像成果物を作る。
一度きりならブラウザの変換ツールの方が速い場合があります。入力がすでに別のシステムにあり、同じスタイルを繰り返し使う場合や、出力を保存・公開・通知へ自動的に渡す場合に API の価値が高まります。
MarkdownToImage にサインインし、API Tokens 画面からトークンを作成します。これはパスワードと同様に扱ってください。ソースコード、Markdown、スクリーンショット、ブラウザ側 JavaScript、エクスポートしたワークフローに書いてはいけません。
ローカルテストでは環境変数として設定します。
export MARKDOWN_TO_IMAGE_API_TOKEN="mti_your_token_here"
本番環境ではホスティング基盤の暗号化されたシークレット保管機能を利用します。公開リポジトリやログにトークンが出た場合は、古いコミットを隠すだけではなく、トークンを失効して作り直してください。
現在の API には、透かし付き出力の月間無料枠があります。透かしなしや大きな利用量は、クレジットまたは最新プランに依存します。実装時に公式ページを確認し、現在の枠を永続的な仕様としてハードコードしないでください。
生成エンドポイントは JSON を受け取り、Bearer 認証を使います。次のリクエストは、幅 1200 ピクセル、GitHub のダークテーマを使った PNG を作成します。
curl -X POST https://markdowntoimage.com/api/v1/images/generate \
-H "Authorization: Bearer $MARKDOWN_TO_IMAGE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"markdown": "# Weekly release\n\n- Faster exports\n- Clearer reports\n- One automated workflow",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url"
}'
URL モードが成功すると、レスポンスの data.imageUrl に結果が入ります。この URL は一時的です。ブラウザで開けば生成成功は確認できますが、永続保存にはなりません。早めにファイルをダウンロードし、自分のオブジェクトストレージ、CMS、メディアライブラリへ保存します。
必須なのは markdown だけですが、自動化では設定を明示して出力を予測可能にすることが重要です。
| パラメーター | 制御する内容 | 実用的な選択 |
|---|---|---|
markdown | 元のコンテンツ | 送信前に長さと必須セクションを検証 |
format | png、jpeg、webp、pdf | コードと UI は PNG、軽い Web 素材は WebP、文書は PDF |
width | 200〜2560 ピクセルの幅 | SNS やレポートは 1200 から始め、実データで確認 |
quality | 1〜3 のデバイススケール | まず 2。大きい値はファイルサイズと処理量を増やす |
theme | 全体のテーマ | 名前付きテーマを固定し、更新による見た目の変化を防ぐ |
codeStyle | シンタックスハイライト | ページテーマとのコントラストを確認 |
fontFamily | フォントプリセット | 製品で使う全言語をテスト |
mode | url または binary | URL は連携向け、binary は直接ファイル処理向け |
写真中心で非可逆圧縮を許容できる場合は JPEG、コードや図、シャープな UI には PNG が適しています。すべての利用先が対応するなら WebP は転送量を減らせます。PDF は同じ生成エンドポイントを使いますが、通常の SNS 画像ではなく文書出力です。
次の Node.js スクリプトは API を呼び出し、HTTP レスポンスを確認し、一時 URL から画像をダウンロードして実ファイルに保存します。現在の Node.js にあるグローバル fetch を使います。
import { writeFile } from "node:fs/promises";
const token = process.env.MARKDOWN_TO_IMAGE_API_TOKEN;
if (!token) throw new Error("MARKDOWN_TO_IMAGE_API_TOKEN is required");
const response = await fetch("https://markdowntoimage.com/api/v1/images/generate", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
markdown: "# Build report\n\n- Tests: **passed**\n- Deploy: **ready**",
format: "png",
width: 1200,
quality: 2,
theme: "github-dark",
mode: "url",
}),
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
throw new Error(`Generation failed: ${response.status} ${await response.text()}`);
}
const result = await response.json();
const imageResponse = await fetch(result.data.imageUrl, {
signal: AbortSignal.timeout(30_000),
});
if (!imageResponse.ok) {
throw new Error(`Download failed: ${imageResponse.status}`);
}
await writeFile("build-report.png", Buffer.from(await imageResponse.arrayBuffer()));
console.log("Saved build-report.png");
Web サービスでは、永続ストレージへのアップロードが完了してからジョブを成功にしてください。API の一時 URL だけを記録して実ファイルをコピーしないと、URL の期限切れ後に遅延障害が発生します。
Python の URL モードも、生成とダウンロードの二段階です。タイムアウトを明示することで、Worker が無期限に待機するのを防ぎます。
import os
from pathlib import Path
import requests
token = os.environ["MARKDOWN_TO_IMAGE_API_TOKEN"]
payload = {
"markdown": "# Build report\n\n- Tests: **passed**\n- Deploy: **ready**",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url",
}
response = requests.post(
"https://markdowntoimage.com/api/v1/images/generate",
headers={"Authorization": f"Bearer {token}"},
json=payload,
timeout=30,
)
response.raise_for_status()
image_url = response.json()["data"]["imageUrl"]
image_response = requests.get(image_url, timeout=30)
image_response.raise_for_status()
Path("build-report.png").write_bytes(image_response.content)
print("Saved build-report.png")
利用量が増えたら、この処理をユーザー向けの長い HTTP リクエスト内ではなくジョブキューで実行します。キューなら同時実行数とリトライを制御し、最終保存 URL も記録できます。
n8n では、Markdown を作成または取得するノードの後に HTTP Request ノードを置きます。トークンを Workflow JSON に貼らず、n8n Credentials に保存してください。
Method: POST
URL: https://markdowntoimage.com/api/v1/images/generate
Authentication: Header Auth
Header name: Authorization
Header value: Bearer {{$credentials.markdownToImageToken}}
Send Body: JSON
Body:
{
"markdown": "{{$json.content}}",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url"
}
二つ目の HTTP Request ノードで {{$json.data.imageUrl}} をダウンロードし、ファイル出力を有効にします。そのバイナリを S3、Google Drive、Directus、WordPress、Slack などへ送ります。認証やクォータの失敗時に空のレコードを公開しないよう、エラー分岐も明示してください。
自動化基盤が JSON を扱いやすく、二回目のダウンロードを実行できるなら URL モードが便利です。キュー、Webhook、ノーコードフローに適していますが、返される URL は一時的です。公式ドキュメントでは現在 24 時間保持とされています。
一回のレスポンスをそのままストレージへ流したい場合は binary を選びます。二回目の HTTP リクエストは不要ですが、クライアント側でバイナリ、Content-Type、拡張子、メモリ上限、不完全なアップロードの削除を正しく扱う必要があります。
どちらでも最終ファイルは自分が管理するストレージに保存します。形式、幅、テーマ、元コンテンツ ID、生成日時、Markdown のハッシュも記録すると、重複防止と障害調査が容易になります。
API では次の主な結果が文書化されています。
| HTTP ステータス | 意味 | 推奨対応 |
|---|---|---|
400 | Markdown がない、またはパラメーターが不正 | 同じ入力を再試行せず、Payload を修正 |
401 | トークンがない、無効、または失効済み | 停止して通知し、Secret を修正または更新 |
429 | 無料枠またはクレジットを利用できない | ジョブを遅延し、担当者へ通知または容量を追加 |
500 | 生成失敗または内部エラー | Backoff を使い、回数を制限して再試行 |
自動リトライは、一時的な障害に限定します。すべての非 200 応答を再試行してはいけません。500 とネットワークタイムアウトには、ジッター付き指数バックオフを使います。接続結果が不明な場合は、同じコンテンツハッシュの出力がすでに保存されていないか確認してから再試行し、一つのジョブで複数回課金されるのを防ぎます。
ログにはステータス、サービス側エラーコード、ジョブ ID、試行回数、遅延を残します。ただし Authorization ヘッダー全体は記録しません。
実トラフィックを送る前に確認してください。
- API トークンはサーバー側の暗号化シークレットに保存;
- 接続と全体のタイムアウトを設定;
- リトライ回数を制限し、ジッター付き指数バックオフを使用;
- Worker の同時実行数をクォータと保存先に合わせる;
- API 呼び出し前に Markdown のサイズと必須項目を検証;
- 形式、幅、テーマ、コードスタイル、フォントを固定;
- URL モードの結果をすぐに永続保存;
- ユーザー入力をそのまま使わず、安全で決定的なファイル名を作る;
- 公開画像に代替テキストと適切な文脈を付ける;
- 使用量を記録し、クォータ枯渇前に通知;
- 多言語フォント、長いコード、表、Mermaid、KaTeX を実データで確認;
- 重要な公開フローに手動の代替手段を用意。
まず少数の代表的な入力で試してください。現実的な Markdown を十件試す方が、数百回の “Hello World” より多くのレイアウト問題を見つけられます。
はい。生成エンドポイントへ format: "png" を送ります。JPEG、WebP、PDF も選べます。コード、本文、図、UI のキャプチャには PNG が最も安全な選択です。
クライアントコードにシークレットトークンを公開してはいけません。サーバー、Serverless Function、保護された自動化フローから呼び出し、保存済みの結果だけをブラウザへ返します。
長さ、内容、安全性を自分の側で確認してから、モデルの Markdown を markdown フィールドへ渡します。安定したプロンプトテンプレートと固定レンダリング設定を使う方が、回答ごとにレイアウトを変えるより一貫したカードになります。
単純な生成、ダウンロード、アップロードなら n8n で十分です。高い同時実行数、独自の冪等性、詳細な可観測性、権限や課金との密接な統合が必要なら Node.js や Python のアプリケーションコードを使います。
製品がすでに生成している Markdown を一つ選び、cURL の例で実行してください。ワークフローを広げる前に、コードの折り返し、表、フォント、画像サイズを確認します。
最初の結果が良ければ、MarkdownToImage API ガイドを開き、サーバー専用トークンを作成し、Node.js、Python、n8n のいずれかを小規模な本番テストへ移します。一種類の実コンテンツ、固定した表示プリセット、永続ストレージ、観測可能なエラー処理から始め、結果を確認してから拡張するのが安全です。