EN ZalogujZałóż konto
Startujemy w październiku 2026. Działają konta, katalog modeli, kalkulator i dokumentacja. Studio jest dostępne w podglądzie; generowanie czeka na uruchomienie.

Generowanie obrazów AI przez API w Pythonie - poradnik

Generowanie obrazów przez API w Pythonie krok po kroku: GPT Image 2.5, Nano Banana Pro i FLUX.2 pro, edycja zdjęć, seria obrazów i obsługa błędów.

Żeby wygenerować obraz AI w Pythonie, wystarczy jedno zapytanie POST z biblioteką requests: podajesz model (np. gpt-image-2.5, nano-banana-pro albo flux-2-pro), prompt i proporcje, a z parametrem ?wait=60 dostajesz gotowy link do pliku w tej samej odpowiedzi. Poniżej pokazuję cały proces na API Jantarisa: od klucza, przez pierwszy obraz, edycję zdjęcia i serię obrazów, po obsługę błędów. Każdy fragment kodu da się skopiować i uruchomić.

Czego potrzebujesz

  • Python 3.10 lub nowszy i biblioteka requests (pip install requests).
  • Konto w Jantarisie i klucz API. Zakładasz je na stronie rejestracji, doładowujesz saldo od 40 zł (BLIK albo karta) i tworzysz klucz sk-jt-... w panelu.
  • Do edycji zdjęć: miejsce, gdzie wystawisz pliki pod publicznym adresem HTTPS (bucket, serwer, CDN).
  • Klucz w zmiennej środowiskowej, nie w kodzie:
bash
export JANTARIS_API_KEY="sk-jt-..."

W PowerShellu: $env:JANTARIS_API_KEY = "sk-jt-...".

Który model do obrazów wybrać

Trzy modele, których używam najczęściej, różnią się bardziej charakterem niż jakością:

ModelCena za obrazMocna stronaKiedy go wybieram
GPT Image 2.50,254 zł za obrazprecyzyjna edycja, trzymanie się poleceń w kolejnych poprawkachgrafiki z instrukcjami krok po kroku, edycje zdjęć
Nano Banana Prood 0,439 zł za obraztekst na obrazie, wiele referencji, spójność postaciplakaty, infografiki, ta sama osoba w kilku scenach
FLUX.2 [pro]od 0,404 zł za obrazfotorealizm, faktury materiałówzdjęcia produktowe, wnętrza, portrety

Kilka faktów od producentów. GPT Image 2.5 (OpenAI, wrzesień 2026) przyjmuje do 16 obrazów referencyjnych i generuje do 4K. Nano Banana Pro, czyli Gemini 3 Pro Image od Google, łączy do 14 obrazów wejściowych i według Google trzyma spójny wygląd do 5 osób. FLUX.2 pro od Black Forest Labs generuje i edytuje do 4 megapikseli i przyjmuje kilka obrazów referencyjnych naraz. Limity obowiązujące w Jantarisie dla każdego modelu sprawdzisz w schemacie parametrów:

bash
curl https://jantaris.com/v1/models/nano-banana-pro

Pole input_schema mówi, które parametry model przyjmuje i jakie mają zakresy. Ten endpoint nie wymaga klucza.

Pierwszy obraz w Pythonie

Obrazy zwykle generują się w kilkanaście, kilkadziesiąt sekund, więc używam parametru ?wait=60. Serwer czeka na wynik i odpowiada gotowym zadaniem. Jeśli nie zdąży, dostajesz kod 202 i odpytujesz zadanie po id.

python
import os
import requests

API = "https://jantaris.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['JANTARIS_API_KEY']}"}

r = requests.post(
    f"{API}/generate",
    params={"wait": 60},
    headers=HEADERS,
    json={
        "model": "gpt-image-2.5",
        "input": {
            "prompt": "Ceramic coffee mug on a concrete kitchen counter, soft morning light, "
                      "shallow depth of field, product photo",
            "aspect_ratio": "1536x1024",  # GPT Image 2.5: rozmiar w pikselach albo "auto"
        },
    },
    timeout=130,  # dłużej niż wait
)
task = r.json()
print(r.status_code, task["status"])

if task["status"] == "succeeded":
    print(task["output"][0]["url"], task["cost"])

Dwie rzeczy łatwo przeoczyć. Timeout klienta musi być dłuższy niż wait, inaczej requests zrezygnuje, zanim serwer odpowie. I zawsze sprawdzaj pole status, bo zakończone zadanie może mieć też failed. Wtedy nic nie płacisz, blokada środków wraca na saldo.

Funkcja pomocnicza: generowanie, czekanie i zapis

W prawdziwym skrypcie opakowuję to w jedną funkcję, która obsługuje też przypadek, gdy 60 sekund nie wystarczy:

python
import time
import pathlib


def wait_for_task(task_id: str, timeout: int = 300) -> dict:
    deadline = time.time() + timeout
    while time.time() < deadline:
        task = requests.get(f"{API}/tasks/{task_id}", headers=HEADERS, timeout=30).json()
        if task["status"] in ("succeeded", "failed"):
            return task
        time.sleep(3)
    raise TimeoutError(task_id)


def generate_image(model: str, prompt: str, folder: str = "obrazy", **params) -> list[pathlib.Path]:
    r = requests.post(
        f"{API}/generate",
        params={"wait": 60},
        headers=HEADERS,
        json={"model": model, "input": {"prompt": prompt, **params}},
        timeout=130,
    )
    if r.status_code not in (200, 202):
        err = r.json()["error"]
        raise RuntimeError(f"{r.status_code} {err['type']}: {err['message']}")

    task = r.json()
    if task["status"] not in ("succeeded", "failed"):
        task = wait_for_task(task["id"])
    if task["status"] == "failed":
        raise RuntimeError(f"generacja nieudana (0 zł): {task['error']['message']}")

    pathlib.Path(folder).mkdir(exist_ok=True)
    paths = []
    for i, item in enumerate(task["output"]):
        path = pathlib.Path(folder) / f"{model}_{task['id']}_{i}.png"
        path.write_bytes(requests.get(item["url"], timeout=60).content)
        paths.append(path)
    return paths


print(generate_image("nano-banana-2", "Scandinavian living room, linen sofa, oak floor, overcast daylight",
                     aspect_ratio="16:9", num_images=2))

Linki w output są ważne ograniczony czas, dlatego funkcja od razu zapisuje pliki na dysku. Rozszerzenie .png to uproszczenie, jeśli potrzebujesz dokładnego formatu, sprawdź nagłówek Content-Type przy pobieraniu.

Parametry, które naprawdę coś zmieniają

Parametry wspólne dla modeli obrazów w API Jantarisa:

ParametrWartościDo czego
prompttekstopis obrazu albo polecenie edycji
image_urlslista adresów HTTPSedycja albo referencje (limit liczby zdjęć zależy od modelu)

Reszta zależy od modelu. aspect_ratio w FLUX.2 pro i Nano Banana Pro to proporcje typu 4:3, a w GPT Image 2.5 rozmiar w pikselach (1024x1024, 1536x1024, 1024x1536) albo auto. num_images, seed, negative_prompt, resolution i quality mają tylko niektóre modele. Dokładną listę pól i dozwolonych wartości zwraca GET /v1/models/{id} w polu input_schema. Pole albo wartość spoza schematu kończy się błędem 422, zanim cokolwiek zapłacisz.

num_images (1-4) przyjmują m.in. Nano Banana 2 i Wan 2.7 Image. GPT Image 2.5, Nano Banana Pro i FLUX.2 pro zwracają jeden obraz na zadanie, więc kilka wariantów to kilka zadań. num_images mnoży koszt: cztery warianty to czterokrotność ceny za obraz. Przy szukaniu kompozycji biorę 2-4 warianty, wybieram najlepszy i dalej poprawiam już tylko jego, edycją zamiast losowania od nowa.

seed przydaje się, gdy chcę zmienić jedno słowo w prompcie i zobaczyć, co się zmienia. Mają go m.in. FLUX.2 [max], FLUX.1 Kontext [pro] i Wan 2.7 Image, a trzy modele z tego poradnika go nie przyjmują. Ten sam seed i ten sam prompt dają podobny wynik, choć nie zawsze identyczny co do piksela.

Edycja zdjęcia przez API

Edycja to ten sam endpoint, tylko z image_urls. Zdjęcie musi być dostępne pod publicznym adresem HTTPS, np. w twoim buckecie albo na serwerze.

python
paths = generate_image(
    "gpt-image-2.5",
    "Replace the background with a bright white studio backdrop. "
    "Keep the product, its shadow and its label exactly as they are.",
    image_urls=["https://twoja-domena.pl/pliki/buty-surowe.jpg"],
)

Przy edycji piszę w prompcie wprost, co ma zostać bez zmian. Bez tego modele lubią "poprawić" przy okazji rzeczy, o które nie prosiłem, np. kolor produktu. GPT Image 2.5 jest w tym najbardziej posłuszny, dlatego do edycji zdjęć produktowych wybieram go najczęściej.

Kilka referencji naraz, np. ta sama postać w nowej scenie:

python
paths = generate_image(
    "nano-banana-pro",
    "The woman from the first image sits at the cafe table from the second image, "
    "reading a book, same outfit, evening light",
    image_urls=[
        "https://twoja-domena.pl/pliki/postac.jpg",
        "https://twoja-domena.pl/pliki/kawiarnia.jpg",
    ],
    aspect_ratio="9:16",
)

Więcej przykładów edycji z polskimi promptami jest w tekście Nano Banana Pro po polsku.

Seria obrazów równolegle

Kiedy potrzebuję 30 grafik do artykułów albo 20 wariantów banera, nie czekam na każdą osobno. Wysyłam kilka zadań równolegle przez ThreadPoolExecutor:

python
from concurrent.futures import ThreadPoolExecutor, as_completed

PROMPTY = [
    "Flat illustration of a person budgeting on a laptop, pastel colors",
    "Flat illustration of a family planting a tree, pastel colors",
    "Flat illustration of a cyclist in the city, pastel colors",
    "Flat illustration of a woman reading in a hammock, pastel colors",
]

with ThreadPoolExecutor(max_workers=4) as pool:
    futures = {pool.submit(generate_image, "flux-2-pro", p, aspect_ratio="16:9"): p for p in PROMPTY}
    for f in as_completed(futures):
        try:
            print("OK", f.result())
        except Exception as e:
            print("BŁĄD", futures[f], e)

Nie przesadzaj z liczbą wątków. Domyślny limit to 60 zapytań na minutę na klucz, po przekroczeniu dostajesz 429. Cztery do ośmiu równoległych zadań to u mnie rozsądny zakres.

Jak pisać prompty do obrazów w API

W skryptach prompt często składam z kawałków, np. z nazwy produktu z bazy i stałego opisu stylu. Taki szablon trzymam w jednym miejscu:

python
STYL = "product photo, soft daylight from the left, neutral background, shallow depth of field"

def prompt_produktu(nazwa: str, material: str) -> str:
    return f"{nazwa} made of {material}, centered, {STYL}"

print(prompt_produktu("Coffee mug", "matte sand-colored ceramic"))

Dzięki temu cała seria ma ten sam styl, a zmiana oświetlenia w 200 obrazach to edycja jednej linijki. Kilka zasad, które u mnie poprawiły wyniki:

  • Najpierw obiekt, potem otoczenie, na końcu światło i kadr. Modele zwracają większą uwagę na początek promptu.
  • Konkretne słowa zamiast ocen: "matte ceramic, visible glaze drips" zamiast "beautiful mug".
  • Tekst, który ma się pojawić na obrazie, w cudzysłowie i w dokładnym brzmieniu.
  • Przy serii ten sam seed dla wszystkich obrazów, jeśli chcesz podobnej kompozycji (w modelach, które mają to pole).
  • Zapisuj prompt razem z plikiem, np. w nazwie albo w pliku JSON obok. Po miesiącu nie będziesz pamiętać, co dało ten dobry wynik.

Obsługa błędów

Koderror.typeCo zrobić
401authentication_errorsprawdź klucz w zmiennej środowiskowej
402insufficient_balancedoładuj saldo, available jest niższe niż szacowany koszt
404not_foundliterówka w nazwie modelu
422invalid_requestparametr poza schematem, komunikat mówi, które pole
429rate_limitodczekaj i ponów z opóźnieniem

Prosty wrapper z ponawianiem przy 429 i 502:

python
def post_with_retry(payload: dict, tries: int = 4) -> requests.Response:
    for attempt in range(tries):
        r = requests.post(f"{API}/generate", params={"wait": 60}, headers=HEADERS,
                          json=payload, timeout=130)
        if r.status_code not in (429, 502):
            return r
        time.sleep(2 ** attempt * 3)
    return r

Pełna lista kodów jest w dokumentacji błędów, a opis endpointu w dokumentacji generowania.

Ile to kosztuje

Każdy model ma cenę za obraz: 0,254 zł za obraz dla GPT Image 2.5, od 0,439 zł za obraz dla Nano Banana Pro i od 0,404 zł za obraz dla FLUX.2 pro. Seria 30 obrazów to trzydziestokrotność ceny jednego, a kwotę dla każdego zadania widzisz w polu estimated_cost od razu po jego wysłaniu. Nieudane generacje nie są płatne.

Na koncie PL ceny są w złotówkach brutto, a fakturę VAT dostajesz po każdym doładowaniu. Aktualne stawki: cennik. Jeśli z obrazu chcesz potem zrobić wideo, obraz podajesz jako pierwszą klatkę, co opisałem w poradniku Seedance 2.5 API.

FAQ

Jak wygenerować obraz AI w Pythonie?

Wyślij POST https://jantaris.com/v1/generate?wait=60 z nagłówkiem Authorization: Bearer sk-jt-... i ciałem {"model": "gpt-image-2.5", "input": {"prompt": "..."}}. W odpowiedzi, w polu output, dostaniesz link do gotowego obrazu.

Który model jest najlepszy do tekstu na obrazie?

Do napisów na plakatach i infografikach najczęściej wybieram Nano Banana Pro. Przy polskich znakach zawsze sprawdzam ogonki, bo błędy w diakrytykach wciąż się zdarzają.

Czy mogę edytować własne zdjęcia przez API?

Tak. Podaj adres zdjęcia w image_urls i opisz w prompcie zmianę oraz to, co ma zostać bez zmian. Plik musi być dostępny pod publicznym adresem HTTPS.

Ile obrazów mogę wygenerować w jednym zapytaniu?

W modelach z parametrem num_images, np. Nano Banana 2, od 1 do 4. GPT Image 2.5, Nano Banana Pro i FLUX.2 pro zwracają jeden obraz na zadanie. Każdy obraz jest liczony osobno, więc koszt rośnie proporcjonalnie.

Czy płacę za obraz, który się nie wygenerował?

Nie. Zadanie ze statusem failed kosztuje 0, a zablokowana kwota wraca na saldo.