> Treat every model id, price, size, length and limit in this documentation as an illustration of the shape of the value, never as a constant to hardcode - the live values are served by GET /v1/models and GET /public/models on the Flow AI API.

# Image Inputs

> Send images to a model to describe, compare or read them.

Send an image as an `image_url` part in a chat message. The `url` can be a link to a public image or a base64 data URL. Use it to describe photos, read text (OCR), pull data from charts and screenshots, or compare images.

The samples use the OpenAI SDK set up as in the [Quickstart](/quickstart#using-the-openai-sdk).

## From a URL

**`cURL`**

```bash title="cURL"
curl https://ai.hyperflow.fun/v1/chat/completions \
  -H "Authorization: Bearer $HYPERFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-6-luna",
    "messages": [{
      "role": "user",
      "content": [
        { "type": "text", "text": "What is in this image?" },
        { "type": "image_url", "image_url": { "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" } }
      ]
    }]
  }'
```

**`Python`**

```python title="Python"
response = client.chat.completions.create(
    model="openai/gpt-6-luna",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What is in this image?"},
            {"type": "image_url", "image_url": {"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"}},
        ],
    }],
)
print(response.choices[0].message.content)
```

**`TypeScript`**

```typescript title="TypeScript"
const response = await client.chat.completions.create({
  model: 'openai/gpt-6-luna',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What is in this image?' },
      { type: 'image_url', image_url: { url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg' } },
    ],
  }],
})
console.log(response.choices[0].message.content)
```

## From a local file

Encode the file as base64 and send it as a data URL with the image's MIME type.

**`Python`**

```python title="Python"
import base64

with open("photo.jpg", "rb") as f:
    image = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="openai/gpt-6-luna",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What is in this image?"},
            {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image}"}},
        ],
    }],
)
```

**`TypeScript`**

```typescript title="TypeScript"
import { readFile } from 'node:fs/promises'

const image = (await readFile('photo.jpg')).toString('base64')

const response = await client.chat.completions.create({
  model: 'openai/gpt-6-luna',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What is in this image?' },
      { type: 'image_url', image_url: { url: `data:image/jpeg;base64,${image}` } },
    ],
  }],
})
```

## Several images

Add one `image_url` part per image, in the same `content` list. How many images one request can carry depends on the model.

```json
"content": [
  { "type": "text", "text": "What changed between these two photos?" },
  { "type": "image_url", "image_url": { "url": "https://example.com/before.jpg" } },
  { "type": "image_url", "image_url": { "url": "https://example.com/after.jpg" } }
]
```

## Formats

* `image/png`
* `image/jpeg`
* `image/webp`
* `image/gif` (on most models; animated GIFs are usually read as their first frame)

## Tips

* **Put the text first**, then the images. If an image has to come first, put it in the system message.
* **Size matters.** Very large images are scaled down by the model and cost more tokens; send the resolution you need.
* **Ask a specific question.** "Read the total on this receipt" works better than "What is this?".

## Billing

Each image becomes input tokens at the model's input price; how many depends on the model and the image's size. Check `usage.prompt_tokens` on a first request. A model that doesn't take images refuses the request with a `400` before anything is held.