GPT Image 2.5 is live — OpenAI's newest image model, targeted edits that leave the rest of the frame alone
画像モデレーション API 入門:Python と JavaScript のサンプル付き
2026/10/07

画像モデレーション API 入門:Python と JavaScript のサンプル付き

画像モデレーション API の仕組みを解説。画像に適用される有害カテゴリ、URL のみの入力、画像単位の課金、スコアのしきい値、Python と JavaScript のコードを紹介します。

画像モデレーション API は、画像を受け取って有害カテゴリの一覧に照らしてスコアを付け、公開・保留・ブロックのどれにすべきかを返します。ただし omni-moderation-latest のような汎用モデルには落とし穴があります。報告されるカテゴリのすべてが実際に画像を見ているわけではありません。OpenAI のドキュメントでは、13カテゴリのうち6つが「Text and images」、残り7つが「Text only」とされています[1]。キャプションなしで写真を送ると、テキスト専用の7カテゴリは仕様として0を返します。写真に問題がないから0になるわけではありません[1]。

このガイドでは、それが実務で何を意味するかを説明します。画像に対して信頼できるカテゴリはどれか、画像の送り方(reAPI は公開 URL のみ受け付けます)、リクエストの課金方法、スコアを判定に変える方法、そして画像を送信して判定結果をポーリングする、そのまま動く Python と JavaScript のサンプルです。最後に、Sightengine、Hive、Azure AI Content Safety、Amazon Rekognition といった画像特化型サービスとの違いを整理します。

TL;DR

  • omni-moderation-latest が画像をスコアリングするのは 6カテゴリ、sexual、self-harm、self-harm/intent、self-harm/instructions、violence、violence/graphic です。sexual/minors を含む残り7つはテキスト専用です[1]。
  • reAPI では、画像は 公開 http(s) URL を指定した image_url ブロックとして送ります。Base64 や data: URI は拒否されます[2]。
  • 課金はモデレーションユニット単位です。画像1枚につき1ユニット、テキストは1,000語ごとに1ユニット、1リクエストあたり最低1ユニットです[2]。現在の料金はモデルページに掲載しています。
  • 呼び出しは非同期です。POST /api/v1/moderations を送り、status が completed になるまで GET /api/v1/tasks/{id} をポーリングします[2]。
  • flagged はモデルのデフォルト判定です。自社ポリシーに合わせるなら、カテゴリごとに category_scores(0〜1)にしきい値を設定し、モデルが更新されたら再調整してください[1]。
  • OpenAI 自身のエンドポイントが無料かどうかは OpenAI のモデレーション API は無料?で解説しています。

画像モデレーション API が判定できる有害カテゴリ

OpenAI は omni-moderation-latest の各カテゴリが対応する入力を公開しています[1]。

カテゴリ入力
sexualテキストと画像
self-harm, self-harm/intent, self-harm/instructionsテキストと画像
violence, violence/graphicテキストと画像
sexual/minorsテキストのみ
harassment, harassment/threateningテキストのみ
hate, hate/threateningテキストのみ
illicit, illicit/violentテキストのみ

画像パイプラインにとって重要な帰結が2つあります。

1つ目は、0が必ずしも測定結果ではないことです。OpenAI によると、テキストを添えずに画像だけを送った場合、テキスト専用カテゴリのスコアは0になります[1]。ミーム画像に含まれるヘイトシンボルや、スクリーンショット内に書かれた脅迫文は、画像だけのリクエストの hate や harassment スコアでは検出されません。各カテゴリがどの入力タイプに対して評価されたかは、レスポンスの category_applied_input_types に示されます。OpenAI の画像のみの例では、画像対応の6カテゴリが ["image"]、それ以外は空配列になっています[1]。低いスコアを合格とみなす前に、このフィールドを確認してください。

2つ目は、sexual/minors がテキスト専用であることです[1]。OpenAI のガイドは、既知の、または疑いのある児童性的虐待コンテンツを Moderation API に送らないようにとも述べています。このモデルは CSAM 検出用に設計されておらず、専用の児童保護対策の代わりにはならないためです[1]。ユーザーのアップロードを受け付けるプラットフォームなら、児童保護のための仕組みを別途用意してください。

OpenAI はこのモデルの画像ファイルの上限を 20 MB としています[1]。

画像の送り方:公開 URL のみ

リクエストボディのコンテンツフィールドは input の1つだけです。画像の場合はコンテンツブロックの配列を送ります[2]。

{
  "model": "omni-moderation-latest",
  "input": [
    { "type": "image_url", "image_url": { "url": "https://example.com/upload.jpg" } }
  ]
}

OpenAI 自身の API リファレンスでは、image_url.url には画像 URL と base64 エンコードされた画像データのどちらも指定できるとされています[3]。reAPI が受け付けるのは前者だけです。image_url.url は公開 http(s) URL でなければならず、base64 や data: URI はエラー 20003 でバリデーションに失敗します[2]。このルールは reAPI のすべてのモデルのメディア入力に適用されます。

ユーザーのアップロードに当てはめると、処理の順序は「ファイルを保存する、インターネットから取得できる URL を用意する、モデレーションする」となります。署名付き URL も、タスク実行時に有効であれば使えます[2]。URL を取得できない場合、タスクは 80007 で失敗し、料金は返金されます[2]。判定結果が返ってくるまで、オブジェクトは非公開のまま公開しないでおきましょう。

キャプションと写真を同じ配列に入れることもできます。reAPI のドキュメントにあるとおり、コンテンツブロックの配列はセット全体に対して1つの結果を返すため、モデルはテキストと画像をまとめて判定します[2]。キャプション付きの投稿ならこれが望ましい動作です。一方、互いに無関係な10件のアップロードには向きません。まとめた1つの判定では、どの画像が原因かわからないので、別々のリクエストで送ってください。

画像モデレーションの課金方法

reAPI は omni-moderation-latest をモデレーションユニット単位で課金します[2]。

入力ユニット
image_url ブロック1つごと1ユニット
テキストリクエスト全体の合計で1,000語ごとに1ユニット。各テキスト項目は最低50語として数える
すべてのリクエスト最低1ユニット

ユニットはリクエストごとに1回クレジットへ換算されて切り上げられ、ポーリングは無料、失敗したリクエストは自動で返金されます[2]。1リクエストで最大500項目まで送れます[2]。ユニット単価はモデルページに掲載しています。ベンダー横断の料金と無料枠の比較は OpenAI のモデレーション API は無料?をご覧ください。

Python と JavaScript による画像モデレーション API のサンプル

どちらのサンプルも同じ処理をします。画像を1枚送信し、3秒ごとにタスクをポーリングして、最初の結果を返します。reAPI のタスクドキュメントは、ポーリング間隔を2〜3秒より短くしないよう推奨しています。タスクの処理中、ポーリング用エンドポイントは5秒間キャッシュされるためです[4]。モデレーションのチェックは通常数秒以内に終わります[2]。

Python

import time
import requests

API = "https://reapi.ai/api/v1"
HEADERS = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
}

def moderate_image(image_url, timeout_s=60):
    submit = requests.post(
        f"{API}/moderations",
        headers=HEADERS,
        json={
            "model": "omni-moderation-latest",
            "input": [{"type": "image_url", "image_url": {"url": image_url}}],
        },
        timeout=30,
    )
    submit.raise_for_status()
    task_id = submit.json()["id"]

    deadline = time.time() + timeout_s
    while time.time() < deadline:
        time.sleep(3)
        task = requests.get(f"{API}/tasks/{task_id}", headers=HEADERS, timeout=30).json()
        if task["status"] == "completed":
            return task["output"]["moderation"]["results"][0]
        if task["status"] == "failed":
            raise RuntimeError(f'{task["error"]["code"]}: {task["error"]["message"]}')
    raise TimeoutError(f"task {task_id} still processing")

result = moderate_image("https://example.com/upload.jpg")
print(result["flagged"], result["category_scores"]["violence"])

JavaScript(Node.js 18+、.mjs モジュールとして保存)

const API = "https://reapi.ai/api/v1";
const headers = {
  Authorization: `Bearer ${process.env.REAPI_API_KEY}`,
  "Content-Type": "application/json",
};

async function moderateImage(imageUrl, timeoutMs = 60_000) {
  const submit = await fetch(`${API}/moderations`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "omni-moderation-latest",
      input: [{ type: "image_url", image_url: { url: imageUrl } }],
    }),
  });
  if (!submit.ok) throw new Error(`submit failed: ${submit.status} ${await submit.text()}`);
  const { id } = await submit.json();

  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    await new Promise((r) => setTimeout(r, 3000));
    const task = await (await fetch(`${API}/tasks/${id}`, { headers })).json();
    if (task.status === "completed") return task.output.moderation.results[0];
    if (task.status === "failed") throw new Error(`${task.error.code}: ${task.error.message}`);
  }
  throw new Error(`task ${id} still processing`);
}

const result = await moderateImage("https://example.com/upload.jpg");
console.log(result.flagged, result.category_scores.violence);

JavaScript 版はブラウザではなくサーバーで実行してください。API キーは Bearer トークンなので、フロントエンドのコードに含めると、開発者ツールを開いた誰にでも見えてしまいます。下の FAQ にある React の質問も同じ理由です。テキストや混在入力を含む完全なリクエストスキーマは API ドキュメントにあります。

結果の読み方としきい値の設定

各結果には4つのフィールドがあります[1][2]。

フィールドわかること
flaggedモデルが少なくとも1つのカテゴリで入力を有害と判断した場合に true
categoriesカテゴリごとのモデルの true/false 判定
category_scoresカテゴリごとのモデルの確信度(0〜1)
category_applied_input_types各カテゴリがどの入力タイプ(text、image)に対して評価されたか

最初の判定には flagged で十分ですが、これはモデルのデフォルト基準を反映したもので、自社ポリシーより厳しいことも緩いこともあります[2]。OpenAI のガイダンスは、スコアを自動ブロックの判断としてではなく、アプリケーションのポリシーに使うシグナルとして扱い、必要に応じてフラグの立ったコンテンツをレビューに回すことです[1]。

よくある形は、画像カテゴリごとに3段階に分ける方法です。低スコア未満は許可、中間は人によるレビュー、高スコア以上はブロックします。最小構成の例は次のとおりです。

IMAGE_CATEGORIES = [
    "sexual", "self-harm", "self-harm/intent", "self-harm/instructions",
    "violence", "violence/graphic",
]
REVIEW_AT = 0.3   # example values only; calibrate on your own labeled images
BLOCK_AT = 0.8

def decide(result):
    applied = result["category_applied_input_types"]
    scores = result["category_scores"]
    checked = [c for c in IMAGE_CATEGORIES if "image" in applied.get(c, [])]
    top = max((scores[c] for c in checked), default=0.0)
    if top >= BLOCK_AT:
        return "block"
    if top >= REVIEW_AT or result["flagged"]:
        return "review"
    return "allow"

上の数値は説明用であり、推奨値ではありません。ラベル付け済みの画像を数百枚流して、スコアがどこに分布するかを見たうえで決めてください。このチェックは定期的にやり直しましょう。OpenAI は基盤モデルを今後もアップグレードしていく予定であり、category_scores に基づく独自ポリシーは時間とともに再調整が必要になる可能性があると述べています[1]。reAPI を経由してもスコアは丸められたり変換されたりしません[2]。そのため一度行った調整は、コードが読み取る値にそのまま適用できます。

画像特化型モデレーション API との違い

汎用モデルと画像特化型サービスは、答える問いが異なります。omni-moderation-latest は6つの視覚カテゴリをスコアリングし、キャプションと画像をまとめて判定できます[1]。画像特化型 API は、武器、薬物、ヘイトシンボル、画像内のテキストなど、はるかに多くの視覚クラスを検出し、ファイルの受け取り方や確信度の報告方法もそれぞれ異なります。各ベンダーのドキュメントから整理すると次のとおりです。

サービス画像で検出するもの画像の送り方出力課金単位
reAPI の omni-moderation-latest性的コンテンツ、自傷(3)、暴力(2)[1]公開 http(s) URL[2]カテゴリごとの真偽値 + 0〜1 スコア[1]画像1枚ごと(モデレーションユニット)[2]
Sightengine29クラスにわたるヌード、暴力、武器、ヘイト・攻撃的なサイン、ゴア、自傷、薬物、アルコール、タバコ、ギャンブル、画像内テキスト、QR コード[5]直接アップロード、または公開アクセス可能な URL[6]選択したモデルごとの結果オペレーション単位。同じグループのモデルは1リクエストにつき1回として数える[7]
Hive Visual Moderation性的コンテンツ、暴力的な画像、薬物、ヘイト画像、画像の属性。名前付きクラスに分類[8]公開 URL または署名付き URL、あるいはローカルファイルのアップロード[9]クラスごとの 0〜1 確信度[9]年間契約。小規模な顧客にはセルフサービスの VLM を案内[8]
Azure AI Content Safety (Analyze Image)Hate、SelfHarm、Sexual、Violence[10]Base64 バイトまたは blob URL のいずれか一方[10]カテゴリごとの重大度 0、2、4、6[11]送信した画像1枚ごと[12]
Amazon Rekognition (DetectModerationLabels)3階層のラベル体系。最上位には Explicit、Violence、Visually Disturbing、Drugs & Tobacco、Alcohol、Rude Gestures、Gambling、Hate Symbols を含む[13]Base64 の画像バイトまたは Amazon S3 オブジェクト。JPEG または PNG[14]確信度付きのラベル。MinConfidence のデフォルトは50[14]API 呼び出しごとの画像1枚単位[15]

選択を左右するのは、主に次の3つの違いです。

視覚的なカバー範囲。 武器、薬物、ヘイトシンボル、画像に焼き込まれたテキストを検出する必要があるなら、特化型サービスはそれらのクラスを明示的に掲げています[5][8][13]。omni-moderation-latest にはそれらに対応する画像カテゴリがありません[1]。

スコアの形式。 Hive はクラスごとに 0〜1 の確信度を返し、クラスにフラグを立てる目安として0.90前後から始めることを勧めています[8]。Rekognition は MinConfidence 未満のラベルを除外し、そのデフォルトは0〜100スケールで50です[14]。Azure は画像に対して 0、2、4、6 という粗い重大度レベルを返します[11]。あるサービスで調整したしきい値は、別のサービスには流用できません。

入力の扱い。 Azure と Rekognition は base64 バイトを受け付け[10][14]、Sightengine と Hive はファイルの直接アップロードを受け付けます[6][9]。reAPI は URL のみです[2]。アップロードがすでにオブジェクトストレージに保存されるパイプラインに適しています。

omni-moderation-latest が向いているのは、コンテンツが主にテキストで画像が添付される場合、6つの視覚カテゴリが自社ポリシーに合っている場合、あるいは同じキーで reAPI 経由ですでに他のモデルを呼び出している場合です。モダリティやユースケース別のより広い比較は、おすすめのコンテンツモデレーション APIをご覧ください。

よくある質問

画像モデレーション API 無料

OpenAI は自社のモデレーションエンドポイントを無料で利用できるとしています[1]。reAPI では omni-moderation-latest は画像1枚につき1ユニットの従量課金で、失敗したリクエストは返金されます[2]。ベンダーごとの無料枠とレート制限の比較は OpenAI のモデレーション API は無料?をご覧ください。

アップロード画像 モデレーション 無料 API

アップロードのモデレーションは3ステップの流れです。ファイルを非公開で保存し、API が取得できる URL を作成し(署名付き URL も有効期間内なら使えます)、その URL を送信して、判定が出てから公開します[2]。reAPI はファイルのバイトや base64 文字列を直接は受け付けません[2]。無料枠があるサービスについては OpenAI のモデレーション API は無料?をご覧ください。

OpenAI 画像モデレーション API

はい、OpenAI のモデレーションモデルは画像に対応しています。omni-moderation-latest はテキストと画像の入力を受け付け、音声は分類せず、画像については sexual、self-harm、violence のカテゴリのみをスコアリングします[1]。reAPI でのモデル ID も同じ omni-moderation-latest で、非同期タスクのエンドポイントの背後で動作します[2]。

画像モデレーション API Python

上の Python サンプルはそれだけで完結しています。image_url ブロックを /api/v1/moderations に POST し、/api/v1/tasks/{id} をポーリングして、output.moderation.results[0] を返します。必要なのは requests パッケージだけです。API ドキュメントには、同じ呼び出しの cURL、Node.js、Go 版が載っています。

画像モデレーション API React

モデレーション API は React コンポーネントからではなく、バックエンドから呼び出してください。React アプリはファイルを自社サーバーかストレージにアップロードし、サーバーがキーを使って API を呼び出し、クライアントは判定結果だけを受け取ります。Bearer キーをブラウザのコードに含めると、すべての訪問者に公開されてしまいます。

ChatGPT API で画像を分析できる?

はい。OpenAI のビジョン対応モデルは、Responses API と Chat Completions API を通じて、URL、base64 データ URL、ファイル ID のいずれかから画像を分析できます[16]。これは自由形式の画像理解です。0〜1 のスコア付きで決まった有害カテゴリを判定したいなら、専用に作られたモデレーションエンドポイントが適しています[1]。

画像モデレーション API おすすめ

何を検出したいかによります。omni-moderation-latest のような汎用モデルは、画像の性的コンテンツ、自傷、暴力をカバーし、キャプション用にテキストカテゴリも備えています[1]。画像特化型サービスはより多くの視覚クラスをカバーします(上の表を参照)。選び方の詳しいガイドはおすすめのコンテンツモデレーション APIにあります。

アップロードフローに画像モデレーションを組み込む

実用的な画像モデレーション API の構成はシンプルです。非公開ストレージにアップロードし、その URL をモデレーションし、スコアに応じて処理し、それから公開します。omni-moderation-latest を使う場合、ピクセルを見ているのは6カテゴリだけだという点を忘れないでください。画像内のテキストが重要なら、キャプションや OCR テキストをリクエストに加え、児童保護のための仕組みは別途用意します。まずは flagged から始め、ラベル付きデータがそろったらカテゴリごとのしきい値に移行し、モデルが変わったらしきい値を見直しましょう。

試すには、Content Moderation のモデルページのプレイグラウンドに画像 URL を貼り付け、そのあと上の Python または JavaScript のサンプルをバックエンドに移してください。この画像モデレーション API が受け付けるすべてのフィールドは API ドキュメントに記載しています。

参考文献

  1. OpenAI. Moderation. 2026年10月に取得。developers.openai.com/api/docs/guides/moderation
  2. reAPI. omni-moderation-latest API docs. reapi.ai/docs/content-moderation
  3. OpenAI. Moderations API reference. 2026年10月に取得。developers.openai.com/api/reference/resources/moderations
  4. reAPI. Tasks API reference. reapi.ai/docs/api/tasks
  5. Sightengine. Visual Moderation models. 2026年10月に取得。sightengine.com/docs/models
  6. Sightengine. What are the ways to send an image to the API? 2026年10月に取得。sightengine.com/faq/ways-to-send-image-to-api
  7. Sightengine. What is an operation? 2026年10月に取得。sightengine.com/faq/what-is-an-operation
  8. Hive. Visual Moderation - Overview. 2026年10月に取得。docs.thehive.ai/docs/visual-content-moderation
  9. Hive. Using Hive's Visual Moderation API. 2026年10月に取得。docs.thehive.ai/docs/visual-moderation-api
  10. Microsoft. Image Operations - Analyze Image (REST API). 2026年10月に取得。learn.microsoft.com/en-us/rest/api/contentsafety/image-operations/analyze-image
  11. Microsoft. Harm categories in Azure AI Content Safety. 2026年10月に取得。learn.microsoft.com/en-us/azure/ai-services/content-safety/concepts/harm-categories
  12. Microsoft. Azure AI Content Safety pricing. 2026年10月に取得。azure.microsoft.com/en-us/pricing/details/content-safety
  13. Amazon Web Services. Using the image and video moderation APIs. 2026年10月に取得。docs.aws.amazon.com/rekognition/latest/dg/moderation-api.html
  14. Amazon Web Services. DetectModerationLabels. 2026年10月に取得。docs.aws.amazon.com/rekognition/latest/APIReference/API_DetectModerationLabels.html
  15. Amazon Web Services. Amazon Rekognition pricing. 2026年10月に取得。aws.amazon.com/rekognition/pricing
  16. OpenAI. Images and vision. 2026年10月に取得。developers.openai.com/api/docs/guides/images-vision