100 free API calls/day -- no credit card needed Get API Access →

AI Image API: Python Tutorial (Free)

By Cemhan Biricik 2026-03-27 12 min read

You can generate AI images from Python in under 10 lines of code. No GPU required, no complex model setup, no dependency headaches. Just send a POST request to an API endpoint and get an image URL back. This tutorial walks through every pattern you need: basic generation, error handling, async workflows, batch processing, and saving images to disk.

We will use the ZSky AI API, which offers 100 free calls per day with no credit card. The same patterns apply to any REST-based image generation API, but ZSky AI is the easiest to start with because there is zero setup friction.

Prerequisites

You need Python 3.7+ and the requests library. If you do not have requests installed:

pip install requests

For async examples later in this tutorial, you will also need:

pip install aiohttp

Step 1: Your First Image Generation

Here is the simplest possible example. This generates a single image from a text prompt and prints the URL where you can download it.

import requests

API_KEY = "sk_live_your_api_key_here"
API_URL = "https://api.zsky.ai/v1/generate/image"

response = requests.post(
    API_URL,
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "prompt": "A mountain lake at sunrise, photorealistic",
        "width": 1024,
        "height": 1024
    }
)

data = response.json()
print(data["image_url"])  # Direct download link, valid 24 hours

That is it. Seven lines of meaningful code. The API handles all the heavy computation on GPU servers and returns a CDN-hosted image URL. You do not need to install any AI frameworks, download model weights, or configure CUDA drivers.

Step 2: Save the Image to Disk

Most workflows need the image as a local file. Here is how to download and save it:

import requests

API_KEY = "sk_live_your_api_key_here"

# Generate the image
response = requests.post(
    "https://api.zsky.ai/v1/generate/image",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "prompt": "Cyberpunk street market at night, neon lights, rain",
        "width": 1024,
        "height": 768,
        "output_format": "png"
    }
)

image_url = response.json()["image_url"]

# Download and save
image_data = requests.get(image_url)
with open("generated_image.png", "wb") as f:
    f.write(image_data.content)

print("Saved to generated_image.png")

Step 3: Error Handling

Production code needs to handle API errors gracefully. The API returns standard HTTP status codes and detailed error messages.

import requests
import time

API_KEY = "sk_live_your_api_key_here"
API_URL = "https://api.zsky.ai/v1/generate/image"

def generate_image(prompt, retries=3):
    for attempt in range(retries):
        try:
            response = requests.post(
                API_URL,
                headers={"Authorization": f"Bearer {API_KEY}"},
                json={"prompt": prompt, "width": 1024, "height": 1024},
                timeout=60
            )

            if response.status_code == 200:
                return response.json()["image_url"]
            elif response.status_code == 429:
                # Rate limited -- exponential backoff
                wait = 2 ** attempt
                print(f"Rate limited. Waiting {wait}s...")
                time.sleep(wait)
            elif response.status_code == 400:
                # Bad request -- do not retry
                print(f"Bad request: {response.json()['error']}")
                return None
            else:
                print(f"Error {response.status_code}: {response.text}")
                time.sleep(1)

        except requests.exceptions.Timeout:
            print(f"Timeout on attempt {attempt + 1}")
        except requests.exceptions.ConnectionError:
            print(f"Connection error on attempt {attempt + 1}")
            time.sleep(2)

    return None

# Usage
url = generate_image("A serene Japanese garden in autumn")
if url:
    print(f"Generated: {url}")
else:
    print("Generation failed after retries")

Step 4: Generate Multiple Images

When you need to generate many images, there are two approaches: the batch endpoint (up to 50 in one call) or concurrent requests with asyncio.

Batch Endpoint

import requests

API_KEY = "sk_live_your_api_key_here"

prompts = [
    "Sunset over the ocean, photorealistic",
    "Snow-capped mountains at dawn",
    "Dense forest with morning fog",
    "Desert dunes under starlight",
    "Tropical waterfall in rainforest"
]

response = requests.post(
    "https://api.zsky.ai/v1/batch",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "requests": [
            {"prompt": p, "width": 1024, "height": 1024}
            for p in prompts
        ]
    }
)

results = response.json()["results"]
for i, result in enumerate(results):
    print(f"Image {i+1}: {result['image_url']}")

Async Concurrent Requests

import asyncio
import aiohttp

API_KEY = "sk_live_your_api_key_here"
API_URL = "https://api.zsky.ai/v1/generate/image"

async def generate(session, prompt):
    async with session.post(
        API_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"prompt": prompt, "width": 1024, "height": 1024}
    ) as response:
        data = await response.json()
        return data["image_url"]

async def main():
    prompts = [
        "Abstract art with bold colors",
        "Minimalist landscape, pastel palette",
        "Portrait in Renaissance style",
        "Sci-fi cityscape at twilight",
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [generate(session, p) for p in prompts]
        urls = await asyncio.gather(*tasks)
        for url in urls:
            print(url)

asyncio.run(main())

The async approach is faster when you are making many individual requests because all requests run concurrently instead of waiting for each one to finish.

Step 5: Advanced Parameters

The API accepts several parameters that give you control over the output:

ParameterTypeDescription
promptstringText description of the image to generate (required)
negative_promptstringWhat to avoid in the output
widthintImage width: 512, 768, 1024, 2048
heightintImage height: 512, 768, 1024, 2048
guidance_scalefloatPrompt adherence (1.0 to 20.0, default 7.5)
seedintReproducible results with same seed
output_formatstringpng, jpeg, or webp
stylestringphotorealistic, stylized, anime, illustration
response = requests.post(
    "https://api.zsky.ai/v1/generate/image",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "prompt": "A cozy cabin in the woods, warm light from windows",
        "negative_prompt": "blurry, low quality, distorted",
        "width": 1024,
        "height": 768,
        "guidance_scale": 8.0,
        "seed": 42,
        "output_format": "webp",
        "style": "photorealistic"
    }
)

Using the same seed with the same prompt and parameters produces identical results, which is useful for reproducible workflows and A/B testing.

Step 6: Build a Flask Wrapper

Here is a minimal Flask app that turns the API into your own image generation microservice:

from flask import Flask, request, jsonify
import requests as http

app = Flask(__name__)
API_KEY = "sk_live_your_api_key_here"

@app.route("/generate", methods=["POST"])
def generate():
    prompt = request.json.get("prompt")
    if not prompt:
        return jsonify({"error": "prompt required"}), 400

    resp = http.post(
        "https://api.zsky.ai/v1/generate/image",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "prompt": prompt,
            "width": request.json.get("width", 1024),
            "height": request.json.get("height", 1024)
        },
        timeout=60
    )

    if resp.status_code == 200:
        return jsonify(resp.json())
    return jsonify({"error": "generation failed"}), 500

if __name__ == "__main__":
    app.run(port=8080)

This gives you a clean internal API that your frontend or other services can call without needing to know the ZSky AI authentication details.

Start Generating Images with Python

100 free API calls per day. No credit card. Get your API key and start building in minutes.

Get Free API Key →

Common Patterns and Tips

Environment Variables for API Keys

Never hardcode API keys in source code. Use environment variables:

import os

API_KEY = os.environ["ZSKY_API_KEY"]
# Set in terminal: export ZSKY_API_KEY=sk_live_your_key

Polling for Async Jobs

For high-resolution images or video, the API returns a job ID. Poll the status endpoint until it completes:

import time

# Submit the job
resp = requests.post(
    "https://api.zsky.ai/v1/generate/image",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={"prompt": "Epic landscape", "width": 2048, "height": 2048}
)
job_id = resp.json()["job_id"]

# Poll until done
while True:
    status = requests.get(
        f"https://api.zsky.ai/v1/status/{job_id}",
        headers={"Authorization": f"Bearer {API_KEY}"}
    ).json()

    if status["status"] == "completed":
        print(f"Done: {status['result_url']}")
        break
    elif status["status"] == "failed":
        print(f"Failed: {status['error']}")
        break

    time.sleep(2)  # Check every 2 seconds

Rate Limit Awareness

Every API response includes rate limit headers. Use them to avoid hitting limits:

remaining = int(response.headers.get("X-RateLimit-Remaining", 0))
reset_time = int(response.headers.get("X-RateLimit-Reset", 0))

if remaining < 5:
    print(f"Only {remaining} requests left. Resets at {reset_time}")

Frequently Asked Questions

What Python libraries do I need to call an AI image API?

You only need the requests library, which comes pre-installed with most Python distributions. For async workflows, use aiohttp or httpx. No special SDK is required since ZSky AI uses a standard REST API that any HTTP client can call.

Is the ZSky AI image API free to use with Python?

Yes. ZSky AI offers 100 free API calls per day with no credit card required. This is enough for prototyping, personal projects, and testing. Paid plans start at $0.02 per image for higher volumes.

How do I handle errors when calling an AI image API from Python?

Check the HTTP status code of the response. 200 means success. 400 means bad request parameters. 429 means rate limited, so implement exponential backoff. 500 means server error, so retry after a short delay. Always wrap API calls in try-except blocks to handle network errors.

Can I generate multiple AI images in a single Python script?

Yes. Use the batch endpoint to send up to 50 prompts in one API call, or use asyncio with aiohttp to send concurrent requests. Both approaches are significantly faster than sequential single-image calls.

How long does it take to generate an AI image via API?

Standard resolution images typically generate in 3 to 8 seconds. Photorealistic and high-resolution images may take 10 to 20 seconds. The API returns a job ID immediately, and you can poll for the result or use a webhook callback.

Build AI-Powered Apps with Python

From prototypes to production. Generate images, videos, and edits with a simple REST API. Free to start.

Get API Access →