AgentSkillsCN

openrouter-image-generation

修复 OpenRouter 图像生成响应解析问题。适用场景如下:(1) 在使用 OpenRouter API 时,搭配诸如 google/gemini-2.5-flash-image 等图像生成模型;(2) 响应中未包含预期的图像数据;(3) 在错误的位置查找 Base64 格式的图像。图像会以 message.images 数组的形式返回,而非采用标准的 OpenAI 格式。本修复方案涵盖了正确的端点调用、响应解析以及 Base64 数据提取流程。

SKILL.md
--- frontmatter
name: openrouter-image-generation
description: |
  Fix for OpenRouter image generation response parsing. Use when: (1) using OpenRouter API
  with image generation models like google/gemini-2.5-flash-image, (2) response doesn't
  contain expected image data, (3) looking for base64 image in wrong location. Images are
  returned in message.images array, not in standard OpenAI format. Covers correct endpoint,
  response parsing, and base64 extraction.
author: Claude Code
version: 1.0.0
date: 2026-01-23

OpenRouter Image Generation Response Format

Problem

When using OpenRouter's image generation models (like google/gemini-2.5-flash-image), the response format differs from expectations. Images are not returned in the standard location, causing parsing failures.

Context / Trigger Conditions

  • Using OpenRouter API (https://openrouter.ai/api/v1/chat/completions) for image generation
  • Model is an image generation model (e.g., google/gemini-2.5-flash-image)
  • Response returns 200 OK but no image found in expected location
  • Looking for image URL or base64 data and not finding it

Solution

1. Use the Chat Completions Endpoint (NOT /images/generations)

python
response = requests.post(
    "https://openrouter.ai/api/v1/chat/completions",  # NOT /images/generations
    headers={
        "Authorization": f"Bearer {OPENROUTER_API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "model": "google/gemini-2.5-flash-image",
        "messages": [{"role": "user", "content": "Generate a pixel art sword"}],
    },
)

2. Extract Image from Correct Location

Images are returned in choices[0].message.images array, NOT in a standard image field:

python
result = response.json()
message = result.get("choices", [{}])[0].get("message", {})
images = message.get("images", [])

if images:
    # Image URL is a base64 data URL
    img_url = images[0].get("image_url", {}).get("url", "")
    # Format: "data:image/png;base64,<base64_data>"

    if img_url.startswith("data:image"):
        # Extract base64 data after the comma
        b64_data = img_url.split(",")[1]
        img_bytes = base64.b64decode(b64_data)

3. Complete Response Structure

json
{
  "choices": [{
    "message": {
      "content": "Here is your image...",
      "images": [{
        "image_url": {
          "url": "data:image/png;base64,iVBORw0KGgo..."
        }
      }]
    }
  }]
}

Verification

  • Check that response.json()["choices"][0]["message"]["images"] exists and has items
  • Verify the image_url.url starts with data:image
  • Decode base64 and write to file - should produce valid image

Example

python
import requests
import base64

def generate_image(prompt: str, api_key: str) -> bytes:
    response = requests.post(
        "https://openrouter.ai/api/v1/chat/completions",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={
            "model": "google/gemini-2.5-flash-image",
            "messages": [{"role": "user", "content": prompt}],
        },
        timeout=120,
    )

    result = response.json()
    images = result["choices"][0]["message"].get("images", [])

    if not images:
        raise ValueError("No image in response")

    img_url = images[0]["image_url"]["url"]
    b64_data = img_url.split(",")[1]
    return base64.b64decode(b64_data)

# Usage
img_bytes = generate_image("A pixel art treasure chest", api_key)
with open("treasure.png", "wb") as f:
    f.write(img_bytes)

Notes

  • All models generate at fixed sizes (typically 1024x1024) regardless of requested size
  • The /images/generations endpoint may return 404 for some models - use chat/completions instead
  • Cost-effective models include google/gemini-2.5-flash-image for pixel art generation
  • Include style instructions in the prompt for consistent results (e.g., "16-bit pixel art, SNES style")

References

  • OpenRouter API Documentation: https://openrouter.ai/docs
  • Available image models can be queried via: GET https://openrouter.ai/api/v1/models