Put the headline on in code: a text-free AI image plus Pillow

When the copy must be exact, ask the model for a text-free image with space for it, then draw the headline in Pillow. The text is then yours, not the model's.

4 min readSume
All posts

When the words must be exact, do not ask the model to draw them. Request a text-free image with an empty area, then draw the headline in code with your own font. The copy is then exactly what you typed, and a typo fix is a one-line change.

Models are getting better at text: Higgsfield lists FLUX 3 Image with more accurate text (Higgsfield changelog, read 2026-10-02). Even so, a regulated price, a legal line, or a brand name is safer when you set it yourself.

What do I ask the image model for?

Describe the scene and the empty space, and say no text. Use aspect_ratio from the model's catalog list, for example 4:5 for Instagram portrait on models that list it.

Split of work, read 2026-10-02
ElementMade byWhy
Scene, product, lightImage model via POST /v1/imagesWhat models are good at
Headline, price, legal lineYour codeExact characters
LogoYour fileExact brand
Final exportPillowFixed size and format

How do I draw the text?

Open the downloaded image, load a font file you licence, and draw with a stroke or a scrim so the text reads on any background. Set FONT to a path on your machine.

import os
from PIL import Image, ImageDraw, ImageFont

FONT = os.environ.get("FONT", "DejaVuSans-Bold.ttf")
image = Image.open("scene.png").convert("RGBA")
width, height = image.size

scrim = Image.new("RGBA", image.size, (0, 0, 0, 0))
ImageDraw.Draw(scrim).rectangle(
    [0, int(height * 0.72), width, height], fill=(0, 0, 0, 120)
)
image = Image.alpha_composite(image, scrim)

draw = ImageDraw.Draw(image)
font = ImageFont.truetype(FONT, size=width // 12)
draw.text((width // 10, int(height * 0.8)), "Free shipping over 50",
          font=font, fill="white")
image.convert("RGB").save("ad.jpg", quality=92)

When is model-drawn text still the right call?

When the text is part of the art, such as a hand-lettered poster, the model has to draw it, and then you review every output. For everything else, code wins on exactness. For many markets, loop the same script with a dictionary of strings instead of one edit call per market; see the price-change edit loop for the edit-based route. Request fields for the image call are in the Image API docs.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume