Skip to content

Gemini Model Image Recognition

Gemini series models support image recognition through the OpenAI-compatible interface. This document uses gemini-3.5-flash as an example to demonstrate how to send an image through the chat.completions interface and get a description.

Basic Configuration

Before using the API, please make sure you have obtained an API Key. If not, please refer to Create API Key.

Basic Information

  • API Base URL: https://api.agentsflare.com/v1
  • Authentication: Bearer Token
  • Content Type: application/json

Request Example

Image Recognition

python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import base64
import mimetypes
import os
import sys

from openai import OpenAI

BASE_URL = "https://api.agentsflare.com/v1"
API_KEY = ""

MODEL = "gemini-3.5-flash"


def file_to_data_url(path: str) -> str:
    if not os.path.isfile(path):
        raise FileNotFoundError(f"File not found: {path}")

    mime, _ = mimetypes.guess_type(path)
    if mime is None:
        mime = "image/jpeg"

    with open(path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode("utf-8")

    return f"data:{mime};base64,{b64}"


def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} /path/to/image.jpg")
        sys.exit(1)

    image_path = sys.argv[1]
    data_url = file_to_data_url(image_path)

    client = OpenAI(
        api_key=API_KEY,
        base_url=BASE_URL,
    )

    resp = client.chat.completions.create(
        model=MODEL,
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "Please analyze this image in detail, describing what you see, the scene, the subject, any text, and any noteworthy details."},
                    {"type": "image_url", "image_url": {"url": data_url}},
                ],
            }
        ],
    )

    print(resp.choices[0].message.content)


if __name__ == "__main__":
    main()
javascript
import fs from "fs";
import path from "path";
import OpenAI from "openai";

const BASE_URL = "https://api.agentsflare.com/v1";
const API_KEY = process.env.AGENTSFLARE_API_KEY || ""; // Recommended to use environment variables
const MODEL = "gemini-3.5-flash";

function fileToDataUrl(filePath) {
  if (!fs.existsSync(filePath)) {
    throw new Error(`File not found: ${filePath}`);
  }

  const ext = path.extname(filePath).toLowerCase();
  let mime = "image/jpeg";
  if (ext === ".png") mime = "image/png";
  else if (ext === ".webp") mime = "image/webp";
  else if (ext === ".gif") mime = "image/gif";

  const buf = fs.readFileSync(filePath);
  const b64 = buf.toString("base64");
  return `data:${mime};base64,${b64}`;
}

async function main() {
  const imagePath = process.argv[2];
  if (!imagePath) {
    console.error(`Usage: ${process.argv[1]} /path/to/image.jpg`);
    process.exit(1);
  }

  if (!API_KEY) {
    console.error("Please set the AGENTSFLARE_API_KEY environment variable or fill in API_KEY in the code.");
    process.exit(1);
  }

  const dataUrl = fileToDataUrl(imagePath);

  const client = new OpenAI({
    apiKey: API_KEY,
    baseURL: BASE_URL,
  });

  const resp = await client.chat.completions.create({
    model: MODEL,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "text",
            text: "Please analyze this image in detail, describing what you see, the scene, the subject, any text, and any noteworthy details.",
          },
          {
            type: "image_url",
            image_url: { url: dataUrl },
          },
        ],
      },
    ],
  });

  console.log(resp.choices?.[0]?.message?.content ?? "");
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
javascript
const fs = require("fs");
const path = require("path");
const OpenAI = require("openai");

const BASE_URL = "https://api.agentsflare.com/v1";
const API_KEY = process.env.AGENTSFLARE_API_KEY || ""; // Recommended to use environment variables
const MODEL = "gemini-3.5-flash";

function fileToDataUrl(filePath) {
  if (!fs.existsSync(filePath)) {
    throw new Error(`File not found: ${filePath}`);
  }

  const ext = path.extname(filePath).toLowerCase();
  let mime = "image/jpeg";
  if (ext === ".png") mime = "image/png";
  else if (ext === ".webp") mime = "image/webp";
  else if (ext === ".gif") mime = "image/gif";

  const buf = fs.readFileSync(filePath);
  const b64 = buf.toString("base64");
  return `data:${mime};base64,${b64}`;
}

async function main() {
  const imagePath = process.argv[2];
  if (!imagePath) {
    console.error(`Usage: ${process.argv[1]} /path/to/image.jpg`);
    process.exit(1);
  }

  if (!API_KEY) {
    console.error("Please set the AGENTSFLARE_API_KEY environment variable or fill in API_KEY in the code.");
    process.exit(1);
  }

  const dataUrl = fileToDataUrl(imagePath);

  const client = new OpenAI({
    apiKey: API_KEY,
    baseURL: BASE_URL,
  });

  const resp = await client.chat.completions.create({
    model: MODEL,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "text",
            text: "Please analyze this image in detail, describing what you see, the scene, the subject, any text, and any noteworthy details.",
          },
          {
            type: "image_url",
            image_url: { url: dataUrl },
          },
        ],
      },
    ],
  });

  console.log(resp.choices?.[0]?.message?.content ?? "");
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
go
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"mime"
	"net/http"
	"os"
	"path/filepath"
)

const (
	BASE_URL = "https://api.agentsflare.com/v1"
	MODEL    = "gemini-3.5-flash"
)

func fileToDataURL(path string) (string, error) {
	info, err := os.Stat(path)
	if err != nil || info.IsDir() {
		return "", fmt.Errorf("File not found: %s", path)
	}

	ext := filepath.Ext(path)
	m := mime.TypeByExtension(ext)
	if m == "" {
		m = "image/jpeg"
	}

	b, err := os.ReadFile(path)
	if err != nil {
		return "", err
	}

	b64 := base64.StdEncoding.EncodeToString(b)
	return fmt.Sprintf("data:%s;base64,%s", m, b64), nil
}

func main() {
	if len(os.Args) < 2 {
		fmt.Printf("Usage: %s /path/to/image.jpg\n", os.Args[0])
		os.Exit(1)
	}
	imagePath := os.Args[1]

	apiKey := os.Getenv("AGENTSFLARE_API_KEY")
	if apiKey == "" {
		fmt.Println("Please set the AGENTSFLARE_API_KEY environment variable.")
		os.Exit(1)
	}

	dataURL, err := fileToDataURL(imagePath)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	reqBody := map[string]any{
		"model": MODEL,
		"messages": []any{
			map[string]any{
				"role": "user",
				"content": []any{
					map[string]any{
						"type": "text",
						"text": "Please analyze this image in detail, describing what you see, the scene, the subject, any text, and any noteworthy details.",
					},
					map[string]any{
						"type": "image_url",
						"image_url": map[string]any{
							"url": dataURL,
						},
					},
				},
			},
		},
	}

	bodyBytes, _ := json.Marshal(reqBody)

	req, err := http.NewRequest("POST", BASE_URL+"/chat/completions", bytes.NewReader(bodyBytes))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	respBytes, _ := io.ReadAll(resp.Body)
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		fmt.Printf("HTTP %d\n%s\n", resp.StatusCode, string(respBytes))
		os.Exit(1)
	}

	var out struct {
		Choices []struct {
			Message struct {
				Content any `json:"content"`
			} `json:"message"`
		} `json:"choices"`
	}
	if err := json.Unmarshal(respBytes, &out); err != nil {
		fmt.Println(string(respBytes))
		return
	}

	if len(out.Choices) == 0 {
		fmt.Println("")
		return
	}

	switch v := out.Choices[0].Message.Content.(type) {
	case string:
		fmt.Println(v)
	default:
		pretty, _ := json.MarshalIndent(v, "", "  ")
		fmt.Println(string(pretty))
	}
}

Note: The size of a single image should not exceed 20M, otherwise the model may return an error.

Supported Models

The following Gemini models support image recognition (Vision) and can be used through this interface (sorted by recommendation):

  • gemini-3.5-flash Recommended
  • gemini-3.1-pro-preview Recommended
  • gemini-3-flash-preview Recommended
  • gemini-3.1-flash-lite New
  • gemini-2.5-pro Deprecated
  • gemini-2.5-flash Deprecated
  • gemini-2.5-flash-lite Deprecated

Note

Models with the image suffix such as gemini-3-pro-image, gemini-3.1-flash-image, and gemini-2.5-flash-image are Nano Banana image generation models, not image recognition models. They cannot be used for chat.completions image recognition requests through this interface.

💡 Tip

The model field in the request example can be replaced with any model name above.

This documentation is licensed under CC BY-SA 4.0.