Pasty 使い方
チームで自前運用している軽量な受け渡し板。テキストかファイルを置くと 6 文字の共有コードが出て、コードだけで受け取れ、期限が来ると自動削除されます。
23456789ABCDEFGHJKMNPQRSTUVWXYZ。見間違えやすい 0/O/1/I/L は除いてあるので口頭で伝えても間違いません。入力時の大文字小文字は問いません。1これは何か
| 項目 | 事実 |
|---|---|
| HTML ページ | AI エージェント向け:トークンを使って HTML ページを 1 つホストし、ブラウザでそのまま開ける /p/ の URL を得る(§9 参照) |
| ログイン | 不要。作成も閲覧も認証なし、コードを持っていれば読めます |
| 内容 | テキスト / ファイル1つ / テキスト+ファイル |
| テキスト上限 | 50,000 文字(JSON エンドポイントは別途リクエスト本体 100KB の制限あり・§4.2) |
| ファイル上限 | 100 MB、1ファイル、形式は自由 |
| 有効期限 | 5分 / 30分 / 1時間 / 1日 / 7日。既定は 1日 |
| 削除 / 編集 / 一覧 | いずれもありません。作成後は取り消せず、期限を待つだけです |
| 保存先 | メタデータとテキストは Redis(TTL 付き)、ファイルは Cloudflare R2 |
向いている用途:自分の端末間でテキストやファイルを移す、目の前の相手にコードを口頭で伝える、Pod やサーバー上の成果物を遠隔の相手に渡す、顧客に短期間だけ有効なダウンロードリンクを渡す。
向かない用途:取り消しが必要なもの、長期保存が必要なもの、鍵・認証情報・個人情報(§7 参照)。
2ウェブでの使い方
2.1 作成する
pasty.youlidao.ai を開くと、既定で「作成」タブです。
- テキスト:入力欄に入力または貼り付け。右下に
使用中 / 50,000が出て、超えると赤くなりボタンが無効になります。 - ファイル(任意):破線の領域にドロップ、クリックして選択、またはテキスト欄にフォーカスがない状態で
⌘V(Windows はCtrl+V)でクリップボードの画像を貼り付け。ファイルは1つだけで、複数落とすと最初の1つだけを取り、その旨を表示します。画像はサムネイル、それ以外はアイコン・名前・サイズ・MIME を表示し、× で外せます。 - 有効期限:ドロップダウン、既定は「1日」。
- 「作成する」を押します。ファイルがある場合はボタンが進捗表示になります。テキストが 50,000 文字超、ファイルが 100MB 超の場合はブラウザ側で送信前に弾きます。
- 結果画面:大きな共有コード、期限、コードのコピー、続けて作成。
2.2 受け取る
- コードで:トップページの「受け取る」タブで 6 文字を入力します。入力欄は自動で大文字化し、集合にない文字は落としますが——黙って消すのではなく、何を無視したかを表示します。6 文字揃って 0.5 秒後に自動で照会して遷移し、ボタンを押せば即座に照会します。存在しないコードは入力欄を空にして知らせます。
- リンクで:
https://pasty.youlidao.ai/{CODE}、大文字小文字は問いません。
2.3 閲覧ページの見え方
右上に残り時間(「残り 4 分」「残り 3 時間」「残り 6 日」)が出ます。その下は内容の種類ごとに:
| 内容 | 表示 |
|---|---|
| テキスト | 等幅の <pre> でそのまま表示(改行とインデントを保持)、下にコピーボタン |
| 画像 | png / jpeg / gif / webp / svg はページ内に表示。クリックで原寸を新しいタブで開きます。下にファイル名とサイズ |
| ブラウザ内蔵ビューアを埋め込み、隣に「新しいタブで開く」と「ダウンロード」。iOS Safari では埋め込み枠に最初の1ページしか出ません——「新しいタブで開く」を使ってください | |
| その他 | zip、Word、Excel、動画など:ファイルカード(アイコン・名前・サイズ・MIME)+ダウンロードボタン |
| テキスト+ファイル | 先にテキスト、添付の区切り線、その下にファイル |
10 秒応答がない場合はタイムアウトを通知します。
2.4 相手への渡し方3種
| 形 | 例 | 向く場面 |
|---|---|---|
| コードだけ | MN3W2R | 口頭・手書き・電話。相手がトップページで入力します |
| ページのリンク | https://pasty.youlidao.ai/MN3W2R | チャットやメール。開けばページ全体が見えます |
| ファイル直リンク | https://pasty.youlidao.ai/api/pastes/MN3W2R/file | 画像と PDF はその場で描画、それ以外はダウンロード。<img> や wget に向きます |
3コマンドライン / スクリプトからの利用
3.1 テキストを送る
curl -s -X POST https://pasty.youlidao.ai/api/pastes \
-H 'Content-Type: application/json' \
-d '{"content":"共有したいテキスト","expiresIn":"1h"}'
# → {"code":"7FZEN4","expiresAt":"2026-09-09T16:56:23.246Z"}
内容がファイル由来のときは、手で エスケープせず jq で JSON を組み立てます:
jq -n --rawfile c notes.md '{content:$c, expiresIn:"1d"}' \
| curl -s -X POST https://pasty.youlidao.ai/api/pastes \
-H 'Content-Type: application/json' --data @-
3.2 ファイルを送る(説明も添えられます)
curl -s -m 120 -X POST https://pasty.youlidao.ai/api/pastes \
-F "file=@/path/レポート.pdf" \
-F "content=これが何かを一言で" \
-F "expiresIn=1h"
# → {"code":"KTCK33","expiresAt":"…","hasFile":true}
- 複数ファイルはまず
zip -rで1つにまとめてください。ファイル用エンドポイントは IP あたり毎分 5 回までなので、ループで1つずつ上げないこと。 type=の指定は不要です。サーバーがファイルの中身から MIME を判定します(§4.4)。- ファイル名は日本語を含む Unicode をそのまま保持します。
3.3 取り出す
# メタデータ+テキスト
curl -s https://pasty.youlidao.ai/api/pastes/KTCK33
# テキストだけ
curl -s https://pasty.youlidao.ai/api/pastes/KTCK33 | jq -r .content
# ファイルをダウンロード(-J でサーバー側の名前、-O で保存)
curl -s -O -J https://pasty.youlidao.ai/api/pastes/KTCK33/file
/raw エンドポイントはありません。GET /{CODE} が返すのはフロントエンドの HTML です。スクリプトからは必ず /api/pastes/{CODE} を叩いて .content を取ってください。
3.4 マシン間でファイルを移すときの推奨手順
# 送信側
shasum -a 256 FILE
curl -s -X POST https://pasty.youlidao.ai/api/pastes -F "file=@FILE" -F "expiresIn=30m"
# 受信側
curl -s -O -J https://pasty.youlidao.ai/api/pastes/CODE/file
shasum -a 256 FILE # 送信側と比較
転送自体は無劣化です(zip / png の往復でバイト一致を実測)。チェックサムはコードの取り違えや途中で切れたダウンロードを検出するためのものです。
JSON テキストしか送れない環境(古いスクリプト、制限付きサンドボックス)では base64 に退避できます:base64 -i FILE | tr -d '\n' を content として送り、受信側で base64 -d。base64 は容積が ×1.33 になり 100KB の本体制限も受けるので、小さなファイル向けです。
4API リファレンス
4.1 エンドポイント一覧
| メソッド | パス | 用途 | レート制限(IP 単位) |
|---|---|---|---|
GET | /api/health | ヘルスチェック | なし |
POST | /api/pastes | application/json = テキストのみ、multipart/form-data = ファイル ± テキスト | JSON は毎分 10 回、multipart は毎分 5 回。カウンタは独立 |
GET | /api/pastes/:code | メタデータ+テキストの取得 | なし |
GET | /api/pastes/:code/file | ファイルのストリーム配信 / プレビュー | なし |
POST | /api/pages | HTML ページを 1 つホスト(トークン必須):JSON の html または multipart の file | 1 分あたり 10 回 |
GET | /p/:code | ホストされたページをサンドボックス CSP 付きで表示 | なし |
GET | /p/:code/pdf | ホストされたページを A4 の PDF に書き出す(初回描画後はキャッシュ) | 1 分あたり 10 回 |
作成時の応答には必ずレート制限ヘッダが付きます:ratelimit-limit、ratelimit-remaining、ratelimit-reset(秒)、ratelimit-policy(例 10;w=60)。超過時は 429 を返し、code は RATE_LIMITED(テキスト)または FILE_RATE_LIMITED(ファイル)です。
4.2 POST /api/pastes · JSON
{ "content": "必須。前後の空白を除いて非空、50,000 文字以内",
"expiresIn": "5m | 30m | 1h | 1d | 7d(省略可、既定は 1d)" }
// 201
{ "code": "7FZEN4", "expiresAt": "2026-09-09T16:56:23.246Z" }
リクエスト本体の上限は 100KB。これは Express の JSON パーサの制限で、文字数チェックより前に効きます。日本語 40,000 文字はおよそ 120KB になり 413 request entity too large が返ります。日本語の長文はおよそ 33,000 文字以内に収めるか、multipart の content フィールド(この制限がなく 50,000 文字まで使えます)に切り替えてください。
検証失敗時の形(details は JSON 経路にのみ付きます):
{ "error": "Content must not be empty",
"code": "CONTENT_EMPTY",
"details": [ { "path": "content", "message": "CONTENT_EMPTY" } ] }
4.3 POST /api/pastes · multipart
| フィールド | 必須 | 規則 |
|---|---|---|
file | content とどちらか | 1ファイル 100MB 以下(104,857,600 バイト)、形式は自由 |
content | file とどちらか | 前後の空白を除いて非空、50,000 文字以内 |
expiresIn | いいえ | 同上、既定は 1d |
201 の応答は { "code", "expiresAt", "hasFile": true }。ファイルがなければ hasFile は付きません。処理順は R2 が先で、成功して初めて Redis に書きます。R2 が失敗すれば何も残らず、Redis が失敗すれば R2 のオブジェクトを消して巻き戻します。
ファイル名の規則:
- 255 文字超 → 400
FILENAME_TOO_LONG ../、..\やその URL エンコード形を含む → 400FILENAME_INVALID、セキュリティログに記録/ \ : * ? " < > |は_に置換、先頭のドットと空白は除去- 名前が空 → MIME から
unnamed.pngのように補完 - 日本語などの Unicode はそのまま保持(以前は latin1 で文字化けしていました)
4.4 MIME の判定 — プレビューかダウンロードかを決める
サーバーはクライアントが申告した Content-Type をそのままは信用せず、次の順で決めます:
- ファイルのマジックナンバー(画像、PDF、zip、Office、音声・動画などのバイナリ形式)
- クライアントの申告。ただし非空かつ
application/octet-streamでない場合のみ(マジックナンバーを持たない txt / csv / json / svg を拾います) - 拡張子
application/octet-stream
その結果、curl -F file=@x.zip は application/zip として保存され、拡張子も申告もない PDF も PDF と認識されてインライン表示でき、PDF を .txt に改名して上げても PDF として扱われます。
4.5 GET /api/pastes/:code
コードはちょうど 6 文字かつすべて集合内でなければ 400 になります。サーバー側で大文字に揃えます。
{
"content": "説明文(ファイルのみのときは空文字列)",
"type": "text | file | mixed",
"fileMetadata": {
"fileName": "スクリーンショット.png", "fileSize": 74, "mimeType": "image/png",
"storageKey": "pastes/U9RBRW/スクリーンショット.png"
},
"createdAt": "2026-09-09T17:00:41.045Z",
"expiresAt": "2026-09-09T17:05:41.045Z"
}
type と fileMetadata はファイルがあるときだけ出ます。初期のテキストのみの記録には type 自体がないことがあり、その場合は text として扱ってください。
4.6 GET /api/pastes/:code/file
ファイル本体をストリームで返します。メモリには溜めません。応答ヘッダ:
| ヘッダ | 値 |
|---|---|
Content-Type | 判定後の MIME |
Content-Disposition | image/* → inline、PDF → inline; filename=…、それ以外 → attachment; filename=…(RFC 5987 エンコードなので非 ASCII 名も安全) |
Content-Length | ファイルサイズ |
Content-Security-Policy | インライン応答(画像・PDF)はサイト基準に sandbox を追加し、スクリプトは一切実行しません。添付応答は基準のままです |
4.7 エラーコード一覧
エラー応答はすべて { "error": <英語の説明>, "code": <識別子> } です。プログラムでの判定には code を使ってください。こちらが安定した契約で、error は人が読むための英語の文章であり表現は変わりえます。ウェブ側は error を表示せず、code から自前の辞書を引いて閲覧者の言語で表示します。
| ステータス | code | 発生する場面 |
|---|---|---|
| 400 | CONTENT_EMPTY | content が空、または空白のみ |
| 400 | INVALID_EXPIRY | expiresIn が 5m/30m/1h/1d/7d のいずれでもない |
| 400 | INVALID_CODE_FORMAT | 共有コードが 6 文字の有効な文字列でない |
| 400 | NO_CONTENT_PROVIDED | multipart に content も file もない |
| 400 | FILENAME_TOO_LONG / FILENAME_INVALID | ファイル名が 255 文字超 / パストラバーサルを含む |
| 400 | VALIDATION_ERROR | multipart が壊れている、またはその他の未分類の検証失敗 |
| 400 | PP_SLUG_INVALID | スラッグの形式・長さが不正、または予約済みパス |
| 401 | PAGE_AUTH_REQUIRED | トークンなし、または誤ったトークンでページを作成しようとした |
| 401 | PP_AUTH_REQUIRED | トークンなし、または誤ったトークンで永久ページを作成した |
| 404 | PASTE_NOT_FOUND | コードが存在しないか期限切れ |
| 404 | NO_FILE_IN_PASTE | そのコードはテキストのみでファイルを含まない |
| 404 | FILE_NOT_FOUND | R2 のオブジェクトが既に整理済み |
| 413 | CONTENT_TOO_LARGE | テキストが 50,000 文字超、または JSON 本体が 100KB 超 |
| 413 | FILE_TOO_LARGE | ファイルが 100MB 超 |
| 413 | PAGE_TOO_LARGE | HTML が 5MB を超えている |
| 409 | PP_SLUG_TAKEN | そのスラッグは既に別の永久ページか有効な共有コードに使われている |
| 429 | RATE_LIMITED / FILE_RATE_LIMITED | テキスト作成 / ファイルアップロードの制限。カウンタは独立 |
| 501 | FILE_UPLOAD_DISABLED | R2 未設定のサーバーにファイルが届いた |
| 501 | PAGE_HOSTING_DISABLED | サーバーに PAGE_API_TOKENS が設定されておらず、ページのホスティングがオフ |
| 501 | PP_HOSTING_DISABLED | サーバーに PP_API_TOKENS が設定されておらず、永久ページ機能が無効 |
| 503 | SERVICE_UNAVAILABLE / SERVICE_BUSY | Redis 障害 / 共有コードの衝突が 5 回続いた |
| 503 | STORAGE_UNAVAILABLE / FILE_UPLOAD_FAILED | R2 が利用不可 / アップロード失敗 |
| 503 | PDF_EXPORT_UNAVAILABLE | PDF の描画に失敗した、待ち行列が満杯、またはサーバーに Chromium が設定されていない |
| 500 | INTERNAL | 捕捉されなかったサーバー側の例外 |
5Claude Code / cc-hub との連携
youlidao.ai の cc-hub セッションと建造センターの Pod には pasty-share skill(v3)が入っています。「これを送って」「このファイルを顧客へ」と AI に頼むと:
- multipart で元のファイルそのものを上げます。skill の鉄則として、PDF や Word を markdown に変換して送ることは禁止されています
- 既定は
expiresIn=1h。複数ファイルはまず zip にまとめます - 共有コードと閲覧リンクを返し、画像と PDF には /file の直リンクも添えます
- 毎回、有効期限と「コードを持つ人は誰でも読める」ことを明示します
skill の禁止事項:.env、秘密鍵、トークン、認証情報、データベースのダンプは送らない。内容が機微かもしれない場合はユーザーに確認する。それでも送るなら 5m / 30m を使う。
6データのライフサイクル
| 段階 | 起きること |
|---|---|
| 作成 | Redis に paste:{CODE} を TTL 付きで書きます。ファイルがあれば先に R2 へ pastes/{CODE}/{名前} |
| 有効期間中 | 回数無制限で読めます。カウントもしません |
| 期限 | Redis のキーが自然に消え、照会は 404 になります |
| 期限後の整理 | サーバーが1時間ごとに走査し、消えた記録に対応する R2 オブジェクトを削除します。R2 側のライフサイクル規則も保険として働きます(文書上は8日) |
| ログ | 構造化ログに残るのは IP、サイズ、MIME、無害化後のファイル名だけで、本文は記録しません |
共有コードは CSPRNG に棄却サンプリングを掛けて一様に生成します。31 の 6 乗 = 887,503,681 通りで、衝突時は最大 5 回まで引き直します。
7安全上の境界(使う前に必読)
- 認証はありません:コードが唯一の鍵で、コードやリンクを手にした人は誰でも読めます。リンクをグループに貼れば全員が読めます。
- 取り消せません:誤って送ったら期限を待つしかありません。迷うときは 5 分か 30 分にしてください。
- 送ってはいけないもの:パスワード、API キー、秘密鍵、証明書、.env、個人情報を含むデータ。
- アップロードした内容は実行されません:画像と PDF のインライン応答には sandbox CSP が付くので、スクリプト入りの SVG を上げても動きません(実ブラウザで確認済み)。HTML や zip は常に添付としてダウンロードされ、描画されません。
- 他サイトから iframe で埋め込めません(
frame-ancestors 'self')。 - 内容ページは検索エンジンに載りません:robots.txt が共有コードのパスのクロールを禁じ、応答にも
X-Robots-Tag: noindexが付きます。これはクローラー対策であって、コードを持つ人には効きません。 - ホストされた HTML ページ(§9)は
/p/{CODE}でのみ表示され、専用のサンドボックス CSP が付きます:別オリジン扱い、API 呼び出し不可、フォーム送信不可。作成にはトークンが必要です。
8よくある質問
- ブラウザで ERR_CONNECTION_CLOSED、または curl が 000 を返す
- 中国本土からの直接接続で時々起きます。再読み込みか一度の再試行で通ります。ヘルスチェックと読み取りのエンドポイント自体は安定しています。
- 作成ボタンが灰色のまま
- テキストが空でファイルも選んでいないか、テキストが 50,000 文字を超えています(カウンタが赤くなります)。
- スマホで PDF の1ページ目しか見えない
- iOS Safari の埋め込み枠の制限です。「新しいタブで開く」を使ってください。
- 日本語のファイル名が文字化けしてダウンロードされる
- 2026-09-10 より前にアップロードされた記録だけです(当時サーバーが latin1 で名前を解釈していました)。以降の分は修正済みで、古い記録は期限で消えます。
- curl で上げた zip が以前 application/octet-stream になっていた
- curl は .zip を知らないので octet-stream と申告し、旧版はそれをそのまま信じていました。今はファイルの中身から判定するので
;type=は不要です。 - 内容の編集・削除・期限の延長はできますか
- できません。そのためのエンドポイントがないので、作り直してください。
- 429 が返ったら
- 応答ヘッダの
ratelimit-reset(秒)だけ待ってください。テキストは毎分 10 回、ファイルは毎分 5 回、IP 単位です。複数ファイルは zip にまとめてください。 - 日本語の長文が 413 request entity too large で送れない
- JSON 本体の上限が 100KB です。multipart の
contentフィールドを使うか、分割してください。 - 画面の言語は変えられますか
- 変えられます。フッターに言語選択(简体中文 / English / 日本語 / 한국어)があり、選択は端末に保存されます。
?lang=jaのように直接指定することもできます。
9HTML ページのホスティング:AI エージェント向けの一時的な Web ページ
9.1 何のための機能か
AI エージェントがレポート、ダッシュボード、プロトタイプを作ったとき、相手に渡したいのはダウンロードするファイルではなく開けばすぐ見られる URL です。HTML ドキュメントを 1 つ POST すると https://pasty.youlidao.ai/p/{CODE} が返り、期限が来ると自動で消えます。
| 項目 | 内容 |
|---|---|
| 作成できる人 | トークンを持つ人:ヘッダー Authorization: Bearer <token>。サーバーにトークンが設定されていない場合は 501 を返し、機能はオフです |
| 閲覧できる人 | 他のコンテンツと同じく、コードやリンクを知っていれば誰でも。ログイン不要 |
| サイズ | HTML ドキュメント 1 つあたり 5 MB まで |
| 有効期限 | 5m / 30m / 1h / 1d / 7d、既定は 1 日 |
| 共有コード | テキストやファイルと同じコード空間。/{CODE} はページのカードを表示し、/p/{CODE} はページを表示します |
| レート制限 | IP ごとに 1 分あたり 10 回 |
9.2 ページを作成する
curl -s -X POST https://pasty.youlidao.ai/api/pages \
-H "Authorization: Bearer $PASTY_PAGE_TOKEN" \
-F "file=@report.html" \
-F "expiresIn=7d"
# → {"code":"MN3W2R","expiresAt":"…","url":"https://pasty.youlidao.ai/p/MN3W2R"}
HTML がすでに変数に入っている場合は JSON で送ります。フィールド名は html です:
jq -n --rawfile h report.html '{html:$h, expiresIn:"1d"}' \
| curl -s -X POST https://pasty.youlidao.ai/api/pages \
-H "Authorization: Bearer $PASTY_PAGE_TOKEN" \
-H 'Content-Type: application/json' --data @-
- 201 のレスポンス:
{ "code", "expiresAt", "url" }。相手に送るのはurlです。 - JSON のリクエストボディはエスケープの分を見込んでページ上限の 2 倍まで受け付けます。5MB に近いページは multipart を使ってください。
- トークンは環境変数に置き、ページ・ログ・チャットには書かないでください。
9.3 開いたときにページができること
/p/{CODE} は text/html; charset=utf-8 として、専用の CSP 付きで返されます:
| できる | できない |
|---|---|
| インラインスクリプト、および次の CDN からのスクリプト:cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com, cdn.tailwindcss.com | 通信:fetch / XHR / WebSocket はすべてブロック(connect-src 'none') |
| インラインスタイル、Google Fonts、data: フォント | フォーム送信(form-action 'none') |
| https / data: / blob: の画像・音声・動画 | iframe や object の埋め込み |
| ポップアップ、外部リンクを新しいタブで開く | localStorage / Cookie:ページは独立したサンドボックス(別オリジン)で動くため、アクセスすると例外になります |
サンドボックスにより、ページのスクリプトは pasty 本体になりすますことも、このサイトの保存データを読むこともできません。外部送信の禁止は、ページをフィッシングフォームとして使わせないためのものですが、完全ではありません(画像 URL やページ遷移でデータを持ち出せます)。本当の関門は作成時のトークンです。
コードが存在しない、期限切れ、またはページではなくテキストやファイルの場合は /{CODE} へ 302 でリダイレクトし、通常の閲覧ページで状況を表示します。匿名のファイルアップロードで送られた .html は常にダウンロード扱いで、/p/ で表示されることはありません。
9.4 ページを書く AI 向けチェックリスト
- 1 ファイルで完結:CSS と JS はインライン、画像は data: URI か https のリンク、ライブラリは cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com, cdn.tailwindcss.com からバージョンを固定して読み込む。
- 通信に頼らない:JSON を fetch せず、データはページに直接書く。
- localStorage を使わない。どうしても使う場合は try/catch で囲み、なくても表示できるようにする。
<meta charset="utf-8">と viewport を書き、スマートフォンでも読めるようにする。中国本土からは Google Fonts が不安定なので、フォントには必ずシステムフォントの代替を指定する。- 有効期限は既定で
1d、人に見せるレポートなら7d。返信ではurlと有効期限を伝え、リンクを知っていれば誰でも見られることを明記する。 - 秘密鍵、個人情報、社内の認証情報は載せない。ルールは §7 と同じ。
機械向けの完全な説明は /llms.txt にあります。
9.5 PDF に書き出す
ホストされたページには右下に「Export PDF」ボタンがあります(ブラウザの言語が中国語の読者には中国語で表示)。リンク先は /p/{CODE}/pdf で、このアドレスをそのまま共有することもできます。
- サーバーが同じ
/p/{CODE}を同じサンドボックス規則のもと Chromium で開き、A4 の PDF にします。背景色は残し、常にライトモードで出力し、ボタン自体は PDF に含めません。 - 初回の書き出しには数秒から 15 秒ほどかかります。結果はキャッシュされ、以降はそのまま返します。PDF はページと同時に期限切れになり、一緒に削除されます。
inlineとファイル名付きで返すため、スマートフォンやアプリ内ブラウザではその場でプレビューでき、パソコンでは保存できます。- レート制限は IP ごとに 1 分あたり 10 回。描画に失敗すると 503
PDF_EXPORT_UNAVAILABLEを返すので、再試行してください。 - きれいに書き出すには、ホバーやクリックで初めて表示される内容を避け、幅の広い表は横スクロールできるコンテナに入れてください。PDF では A4 幅に合わせて折り返されます。