API de geração de imagens do Gemini em Python: exemplo de código

Um passo a passo funcional em Python para a API de geração de imagens do Gemini, usando o modelo atual gemini-3.1-flash-image e a Interactions API. Gere sua primeira imagem, controle a proporção e a resolução, edite fotos, refaça chamadas que falharam e estime o custo real por imagem.

API de geração de imagens do Gemini em Python: exemplo de código
Cristian Da Conceicao
Fundador do Picasso IA

A maioria dos tutoriais de imagens do Gemini ainda chama gemini-2.5-flash-image, e a página de preços do Google lista esse modelo como descontinuado, com data de desativação em 2 de outubro de 2026. Essa data já passou, então os trechos baseados nele devem ser tratados como quebrados. Esta página usa o modelo atual, gemini-3.1-flash-image, e a Interactions API, que a própria documentação do Google agora apresenta em primeiro lugar.

Você vai sair de uma pasta vazia e chegar a um script funcional que gera uma imagem, controla o tamanho, edita uma foto existente, salva a saída mista de texto e imagem e sobrevive aos limites de taxa. Cada trecho é curto o bastante para colar em um arquivo e executar. Uma imagem 1K no modelo Flash padrão custa cerca de US$ 0,067, então os testes continuam baratos.

O que você precisa antes de programar

Desenvolvedor digitando código em uma mesa de madeira com uma caneca de café na luz da manhã

Três coisas separam você da sua primeira imagem: uma instalação recente do Python 3, uma credencial do Google AI Studio e um projeto com o faturamento ativado. A página de preços do Google não mostra nenhum nível gratuito para os modelos de geração de imagens do Gemini, então um projeto sem faturamento provavelmente será rejeitado na primeira chamada.

Instale o SDK

Um único pacote faz tudo:

pip install -U google-genai

A Interactions API precisa de google-genai 2.3.0 ou mais recente, por isso a sinalização -U é importante. Execute pip show google-genai se algum trecho abaixo falhar com um erro de atributo em client.interactions.

Configure sua credencial

Crie uma credencial no Google AI Studio e depois exporte-a como variável de ambiente com exatamente o nome abaixo. O SDK lê essa variável sozinho, então seu script nunca precisa conter o segredo.

export GEMINI_API_KEY="paste-your-credential-here"

No PowerShell do Windows, a mesma linha é $env:GEMINI_API_KEY = "paste-your-credential-here".

💡 Nunca coloque a credencial em um script que vai para o Git. Mantenha-a em uma variável de ambiente ou em um arquivo .env que seu .gitignore já exclui.

Escolha um modelo

O Google agora lista quatro modelos de geração de imagens. Três são atuais, e um está aposentado.

ID do modeloTamanhosPreço por imagemMelhor para
gemini-3.1-flash-lite-imageSomente 1Kcerca de US$ 0,034Trabalhos em massa, miniaturas
gemini-3.1-flash-image0.5K, 1K, 2K, 4KUS$ 0,045, US$ 0,067, US$ 0,101, US$ 0,151Escolha padrão para a maioria dos scripts
gemini-3-pro-image1K, 2K, 4KUS$ 0,134 (1K e 2K), US$ 0,24 (4K)Prompts complexos e com várias partes
gemini-2.5-flash-imagen/dUS$ 0,039Aposentado, não use

Os preços vêm da página de preços do Google no momento em que este texto foi escrito. Confira novamente antes de uma execução grande.

Como escolher? Comece com gemini-3.1-flash-image. Ele é o único modelo atual que oferece os quatro tamanhos, então um mesmo caminho de código atende miniaturas e arquivos para impressão. Mude para o Flash Lite quando você gerar milhares de imagens pequenas e cada centavo por imagem contar. Recorra ao Pro quando um prompt tiver muitas partes, como um layout de cartaz com vários elementos rotulados, e um modelo mais barato continuar deixando detalhes de fora. Como os três modelos atuais compartilham a mesma forma de chamada, trocar de modelo depois significa editar uma única string.

Gere sua primeira imagem

Mulher olhando para um monitor que mostra uma fotografia nítida de um lago de montanha

Salve isto como first_image.py:

import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="A photograph of a bowl of oranges on a linen cloth, soft window light",
)

with open("oranges.png", "wb") as f:
    f.write(base64.b64decode(interaction.output_image.data))

Execute python first_image.py e um arquivo oranges.png aparece ao lado do script. Esse é todo o ciclo: prompt de entrada, string base64 na saída, bytes gravados em disco.

Quando você gerar mais de uma imagem, um nome de arquivo fixo sobrescreve o resultado anterior. Monte o nome a partir de um carimbo de data e hora, por exemplo f"image_{int(time.time())}.png", e cada execução deixa seu próprio arquivo. Assim você pode comparar uma dúzia de variações de um mesmo prompt lado a lado.

O que cada linha faz

  • genai.Client() cria um cliente e busca a credencial na variável de ambiente que você exportou antes, então nada sensível fica no arquivo.
  • client.interactions.create() envia o prompt e devolve um objeto Interaction que carrega um id, as etapas de saída e atalhos como output_image.
  • interaction.output_image.data guarda a imagem como uma string base64. Você precisa decodificá-la antes de gravar, senão o arquivo será texto, não uma imagem.

Escreva prompts que funcionam

O modelo responde melhor a descrições de cena do que a um amontoado de tags soltas. Um prompt que lê como a lista de planos de um fotógrafo dá mais controle do que uma lista de adjetivos.

  1. Nomeie o sujeito e a ação. "Um padeiro polvilhando farinha sobre um pão" funciona melhor do que "padaria".
  2. Descreva a luz. Luz de janela, céu nublado, hora dourada ou sol forte do meio-dia.
  3. Acrescente lente e distância. "Retrato de 85mm, profundidade de campo rasa" ou "aérea ampla de 24mm".
  4. Diga o que deixar de fora. Uma frase curta, como "sem texto na imagem".

💡 Guarde seus prompts em uma lista Python ou em um arquivo de texto. Quando um resultado surpreender, você pode mudar uma variável e comparar, o que é melhor do que reescrever de memória.

Controle o tamanho e a proporção

Vista de cima de fotografias impressas em proporções largas, altas e quadradas sobre uma mesa de carvalho

Tamanho e formato ficam dentro de um dicionário response_format. Isso confunde muita gente, porque o código antigo colocava as configurações de imagem em generation_config.

interaction = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="A wide photograph of a coastal road at dawn, 35mm lens, film grain",
    response_format={
        "type": "image",
        "mime_type": "image/jpeg",
        "aspect_ratio": "16:9",
        "image_size": "2K",
    },
)

with open("coast.jpg", "wb") as f:
    f.write(base64.b64decode(interaction.output_image.data))

Como o mime_type solicitado é JPEG, o arquivo recebe a extensão .jpg. Combine a extensão com o tipo que você pediu e seu visualizador de imagens nunca vai reclamar.

Proporções que você pode solicitar

A documentação do Google lista dez proporções: 1:1, 3:2, 2:3, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9 e 21:9.

ProporçãoUso típico
1:1Fotos de perfil, miniaturas de produtos
4:5Publicações no feed das redes sociais
9:16Stories e miniaturas de vídeos verticais
16:9Cabeçalhos de blog, miniaturas de vídeo
21:9Banners ultralargos
3:2Impressões de fotos clássicas

Escolha uma resolução

O valor image_size depende do modelo. O Flash Lite oferece somente 1K. O Flash oferece 0.5K, 1K, 2K e 4K. O Pro oferece 1K, 2K e 4K. Use K em maiúsculas no valor.

Uma regra simples mantém os custos sob controle: 1K para rascunhos, 2K para páginas web, 4K somente para impressão. Uma imagem 4K no Flash custa US$ 0,151 contra US$ 0,067 em 1K, cerca de 2,25 vezes mais, então o hábito de "sempre o máximo" se acumula rápido.

Edite uma foto com prompts de texto

Retocador de fotos em uma mesa em pé segurando um retrato impresso ao lado de um monitor calibrado

O mesmo endpoint edita imagens. Em vez de uma string simples, input vira uma lista que mistura blocos de texto e blocos de imagem. A imagem viaja como string base64 com seu tipo MIME.

import base64
from google import genai

client = genai.Client()

with open("portrait.png", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")

interaction = client.interactions.create(
    model="gemini-3.1-flash-image",
    input=[
        {
            "type": "text",
            "text": "Replace the background with a sunlit brick wall. Keep the person unchanged.",
        },
        {"type": "image", "data": encoded, "mime_type": "image/png"},
    ],
)

with open("portrait_edit.png", "wb") as f:
    f.write(base64.b64decode(interaction.output_image.data))

Observe a redação do prompt de edição. Ele diz o que muda (o fundo) e o que permanece (a pessoa). Sem a segunda metade, o modelo fica livre para redesenhar o quadro inteiro.

Encadeie edições em uma conversa

Você não precisa reenviar a imagem a cada ajuste. Passe o id da interação anterior e o modelo lembra da imagem que acabou de criar:

second = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Make the light warmer, like late afternoon.",
    previous_interaction_id=interaction.id,
    response_format={
        "type": "image",
        "mime_type": "image/jpeg",
        "aspect_ratio": "4:5",
        "image_size": "2K",
    },
)

Mantenha a mesma proporção da primeira imagem, senão o modelo pode cortar ou estender a cena. Armazene cada interaction.id no seu banco de dados e você pode voltar a qualquer etapa anterior de uma sessão, o que é útil em trabalhos para clientes, em que "volte para a versão dois" aparece com frequência.

Leia respostas mistas e adicione busca

Mesa de leitura tranquila em uma biblioteca, com notebook aberto, livros e luz da tarde

Às vezes o modelo responde com uma frase de texto e uma imagem. O atalho output_image serve para scripts simples, mas um auxiliar que percorre a lista steps cuida de todos os casos:

def save_outputs(interaction, prefix="gemini", ext="png"):
    saved = []
    for step in interaction.steps:
        if step.type != "model_output":
            continue
        for block in step.content:
            if block.type == "text":
                print(block.text)
            elif block.type == "image":
                path = f"{prefix}_{len(saved) + 1}.{ext}"
                with open(path, "wb") as f:
                    f.write(base64.b64decode(block.data))
                saved.append(path)
    return saved

A função devolve uma lista de caminhos de arquivo. Uma lista vazia significa que o modelo enviou somente texto, o que não é uma exceção, então verifique isso antes de presumir que um arquivo existe.

Ancore prompts com busca

Algumas imagens dependem de fatos que mudam todo dia: um gráfico do tempo, um placar, um gráfico de preços. Ative a Pesquisa Google e o modelo pode buscar dados atualizados antes de desenhar:

interaction = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Create an infographic of this week's weather in Chicago",
    tools=[{"type": "google_search"}],
    generation_config={"thinking_level": "high"},
)

A configuração thinking_level aceita "minimal" ou "high". Use minimal quando a velocidade importar e o layout for simples. Use high quando o prompt pedir um layout estruturado com várias partes.

💡 Toda imagem devolvida pela API traz uma marca d'água SynthID, uma marca invisível que o Google adiciona para que a imagem possa ser identificada como gerada por IA. Você não precisa adicionar uma por conta própria.

Trate os erros antes da produção

Mão de engenheiro segurando um marca-texto amarelo sobre uma página impressa com registros de log

Chamadas de imagem costumam demorar mais do que chamadas de texto, e rajadas de requisições podem acionar limites de taxa. Um pequeno wrapper de repetição poupa você da maior parte dos problemas. Ele repete em caso de HTTP 429, 500 e 503 e espera mais a cada falha:

import time

def generate_with_retry(prompt, retries=4, **kwargs):
    for attempt in range(retries):
        try:
            return client.interactions.create(
                model="gemini-3.1-flash-image",
                input=prompt,
                **kwargs,
            )
        except Exception as exc:
            status = getattr(exc, "status_code", None) or getattr(exc, "code", None)
            if status not in (429, 500, 503) or attempt == retries - 1:
                raise
            time.sleep(2 ** attempt)

Dependendo da versão do SDK, o status HTTP fica em status_code ou em code, então o auxiliar verifica os dois. Qualquer coisa que não possa ser repetida, como uma requisição inválida, é lançada imediatamente para que você veja a mensagem real.

Para processar uma lista de prompts, execute poucos de cada vez:

from multiprocessing.pool import ThreadPool

prompts = ["A bowl of oranges", "A lighthouse at dusk", "A forest road in fog"]

with ThreadPool(4) as pool:
    results = pool.map(generate_with_retry, prompts)

Comece com quatro workers. Se o auxiliar de repetição continuar disparando, reduza para dois antes de aumentar qualquer cota.

Prompts recusados exigem outro hábito. A documentação do Google observa que configurações de segurança personalizadas não são suportadas na Interactions API, então você não pode afrouxar os filtros pelo código. Quando uma resposta voltar com texto e sem imagem, registre o prompt e o texto e depois reescreva o prompt com uma descrição mais calma e mais concreta. Repetir exatamente o mesmo prompt raramente muda a resposta e só consome tempo.

3 erros comuns

  1. Chamar um modelo aposentado. Qualquer trecho com gemini-2.5-flash-image precisa ter a string do modelo trocada por uma atual.
  2. Colocar aspect_ratio em generation_config. Ele pertence a response_format, junto de image_size.
  3. Gravar a string base64 em disco. Execute sempre base64.b64decode() antes, senão o arquivo não abre.

Se você ainda tem código antigo que chama generate_content, o Google diz que essa API continua suportada e agora está marcada como legada. Para projetos novos, a Interactions API é a que a documentação do Google recomenda.

Acompanhe os custos

Pequeno empresário revisando uma fatura impressa ao lado de um notebook em uma oficina de cerâmica

Os custos crescem com o volume, então faça as contas antes de um loop grande. Quinhentas imagens 2K no Flash custam 500 x US$ 0,101, o que dá US$ 50,50. O Google também oferece preço em lote, por cerca de metade da tarifa padrão, para trabalhos que podem esperar:

ResoluçãoPadrãoLote
0.5KUS$ 0,045US$ 0,022
1KUS$ 0,067US$ 0,034
2KUS$ 0,101US$ 0,050
4KUS$ 0,151US$ 0,076

As mesmas 500 imagens em 2K pelo lote custam cerca de US$ 25. Se ninguém estiver esperando o resultado, como uma atualização noturna de catálogo, o lote é o caminho mais barato.

Use o Nano Banana Pro no PicassoIA

Designer jovem diante de um monitor grande mostrando uma grade de fotografias em um estúdio iluminado

Nem toda imagem precisa de um script. Se você quer testar um prompt antes de gastar créditos da API, ou passar o trabalho para um colega que não programa em Python, o Nano Banana Pro no PicassoIA é uma forma sem código de obter saída de até 4K da mesma família de modelos do Google.

  1. Abra a página do modelo. Acesse a página do Nano Banana Pro.
  2. Escreva seu prompt. Use o mesmo estilo de lista de planos de antes: sujeito, luz, lente.
  3. Adicione imagens de referência (opcional). O campo Image Input aceita até 14 imagens que orientam estilo, composição ou sujeito.
  4. Escolha uma proporção. Selecione entre 11 predefinições, incluindo 16:9, 9:16, 4:5, 21:9 e match_input_image.
  5. Escolha uma resolução. 1K, 2K (o padrão) ou 4K.
  6. Escolha um formato. JPG (o padrão) ou PNG.
  7. Defina o filtro de segurança. block_only_high é o padrão e o mais permissivo; block_low_and_above é o mais rigoroso.
  8. Gere e baixe. Execute novamente com um prompt ajustado para comparar versões.

Relacione as configurações da API aos campos da página

Se você faz protótipos na página e depois passa para o código, as configurações quase se alinham uma a uma:

Campo no PicassoIAEquivalente na API Python
Promptinput (bloco de texto)
Image Inputinput (blocos de imagem, base64)
aspect_ratioresponse_format["aspect_ratio"]
resolutionresponse_format["image_size"]
output_formatresponse_format["mime_type"]

A família Google no PicassoIA é mais ampla do que um único modelo. O Nano Banana cuida de edições rápidas, o Nano Banana 2 Lite prioriza velocidade, e o Imagen 4 e o Imagen 4 Ultra focam em detalhes fotorrealistas. Rodar o mesmo prompt em dois deles leva um minuto e mostra qual estilo combina com seu projeto antes de você escrever uma única linha de código de integração.

Crie suas próprias imagens hoje

Dois amigos em uma mesa de café olhando uma fotografia de paisagem em um tablet

Agora você tem todas as peças: uma instalação funcional, a primeira imagem, controle de tamanho e proporção, edições, uma forma segura de ler saídas mistas, um wrapper de repetição e uma estimativa de custo em que você pode confiar. Escolha um trabalho pequeno, como um cabeçalho de blog ou a miniatura de um produto, e execute do início ao fim ainda esta tarde.

Se você prefere ver resultados antes de abrir um terminal, abra o Picasso IA, escolha um modelo como o Nano Banana Pro e digite o prompt que você acabou de escrever para o seu script. Teste três variações, mude a proporção e compare. O melhor prompt que você encontrar ali vai direto para o código Python acima.

Esse ciclo, testar na página e lançar em código, é o caminho mais rápido para definir um visual sem pagar por cada experimento. Abra o Picasso IA, rode seu primeiro prompt e veja o que você pode criar antes que a tarde termine.

Compartilhe este artigo

Escolha seu idioma