live
MODEL IDbfl:flux@3-image

FLUX 3 Image

Black Forest Labs
by
Available with Zero Data Retention

FLUX 3 Image is Black Forest Labs' image generation and editing model built on the multimodal FLUX 3 backbone shared with FLUX 3 Video. It combines text-to-image synthesis, precise local editing, multi-reference composition, bounding-box placement, and native 4K output. The model preserves identities and fine details across references, supports targeted changes and in-place text editing, and renders accurate typography in text-heavy layouts across a broad range of visual styles.

FLUX 3 Image

Rendering text with FLUX 3 Image

How to render readable text with FLUX 3 Image: quoting the exact string, directing the typography, building a text hierarchy, and editing copy inside an existing image.

Introduction

Typography is the part of FLUX 3 Image that changed most from earlier FLUX models, and it is what makes the model usable for work that ships with words on it: packaging, campaign creative, interface mockups and signage.

There are no text layers and no font picker. Every character, its weight, its position and its size come out of the same positivePrompt that describes the scene, which makes the phrasing of the text instruction the whole of the typographic control.

Three strings at three sizes, each one placed by the prompt. This guide covers how to get the characters right, how to direct the typography, how to stack several strings into a layout, and how to change copy in an image you already have.

Quote the exact string

Put every string you want rendered inside quotation marks. The quotes mark the boundary between the part of the sentence that describes the scene and the part that is literal content, Without them the model writes its own copy from your description: it reads cleanly, and it is not the copy you were handed.

The unquoted prompt asked for a spring sale at thirty percent off and got exactly that. The quoted one got "30% OFF EVERYTHING", a word the description never implied, because the string was handed over instead of described.

The quoted version also carries a size relationship, "large" against "smaller beneath it", which is what turns two strings into a headline and a subhead rather than two lines of equal weight.

Accuracy falls off as strings get longer. A brand name, a headline or a short line of detail render reliably. A paragraph of body copy is where it stops being reliable.

Try in Playground
import { createClient } from '@runware/sdk'

const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()

const [result] = await client.run({
  model: 'bfl:flux@3-image',
  positivePrompt: 'A clothing store window with a vinyl decal reading "SPRING SALE" in large white capitals with "30% OFF EVERYTHING" in smaller white capitals beneath it, applied to the glass, racks of clothing visible inside, a pavement in front. Bright overcast daylight. Straight-on shot from across the pavement at standing height, 35mm lens. Photoreal retail photography, neutral palette.',
  width: 1248,
  height: 832
})
import asyncio
import os

from runware import Runware


async def main():
    async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
        results = await client.run({
            "model": "bfl:flux@3-image",
            "positivePrompt": "A clothing store window with a vinyl decal reading \"SPRING SALE\" in large white capitals with \"30% OFF EVERYTHING\" in smaller white capitals beneath it, applied to the glass, racks of clothing visible inside, a pavement in front. Bright overcast daylight. Straight-on shot from across the pavement at standing height, 35mm lens. Photoreal retail photography, neutral palette.",
            "width": 1248,
            "height": 832
        })


asyncio.run(main())
curl https://api.runware.ai/v1 \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "taskType": "imageInference",
      "taskUUID": "d4e5f6a7-b8c9-0123-def1-234567890123",
      "model": "bfl:flux@3-image",
      "positivePrompt": "A clothing store window with a vinyl decal reading \"SPRING SALE\" in large white capitals with \"30% OFF EVERYTHING\" in smaller white capitals beneath it, applied to the glass, racks of clothing visible inside, a pavement in front. Bright overcast daylight. Straight-on shot from across the pavement at standing height, 35mm lens. Photoreal retail photography, neutral palette.",
      "width": 1248,
      "height": 832
    }
  ]'
runware run bfl:flux@3-image \
  positivePrompt="A clothing store window with a vinyl decal reading \"SPRING SALE\" in large white capitals with \"30% OFF EVERYTHING\" in smaller white capitals beneath it, applied to the glass, racks of clothing visible inside, a pavement in front. Bright overcast daylight. Straight-on shot from across the pavement at standing height, 35mm lens. Photoreal retail photography, neutral palette." \
  width=1248 \
  height=832
{
  "taskType": "imageInference",
  "taskUUID": "d4e5f6a7-b8c9-0123-def1-234567890123",
  "model": "bfl:flux@3-image",
  "positivePrompt": "A clothing store window with a vinyl decal reading \"SPRING SALE\" in large white capitals with \"30% OFF EVERYTHING\" in smaller white capitals beneath it, applied to the glass, racks of clothing visible inside, a pavement in front. Bright overcast daylight. Straight-on shot from across the pavement at standing height, 35mm lens. Photoreal retail photography, neutral palette.",
  "width": 1248,
  "height": 832
}
Response
{
  "data": [
    {
      "taskType": "imageInference",
      "taskUUID": "d4e5f6a7-b8c9-0123-def1-234567890123",
      "imageUUID": "b8c9d0e1-f2a3-4567-2345-678901234567",
      "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/b8c9d0e1-f2a3-4567-2345-678901234567.jpg"
    }
  ]
}

Direct the typography

A quoted string gets the characters right. It does not decide the weight, the case, the color, or how much of the panel the words take up, and left unsaid those are chosen for you.

The directed prompt sets four things the first one left open:

  • Weight and family: "heavy white sans-serif capitals"
  • Coverage: "filling two thirds of the panel width"
  • Position: "centered across it", "beneath it"
  • Relative size: "at a quarter of that size"

Coverage is the one people leave out and then fight with. Saying how much of the surface the text should occupy is more reliable than asking for it to be large, because large is relative to a frame the model has not drawn yet.

Building a layout

Text-heavy work is several strings with a stated relationship between them. Name each string, say where it sits relative to the last one, and give it a size and a weight. The model holds a hierarchy of three or four levels comfortably.

Each of these is one prompt, and each one orders its strings top to bottom in the same order they appear on the surface. Writing the strings in reading order is worth doing deliberately, because a prompt that introduces the footer before the headline tends to come back with them swapped.

Small type is the first thing a lower tier loses. A pricing list or a sidebar of menu labels that reads cleanly at 2K can turn mushy at 0.75K, so generate text-heavy layouts at the tier you intend to deliver rather than proofing at a cheap one.

Editing copy in place

Text is editable the same way anything else is: send the image in inputs.referenceImages and name the string you want changed. Because the type is rebuilt rather than overlaid, the replacement picks up the surface it sits on, including its curve, its finish and the light across it.

A white supplement carton reading NORDVIT, Magnesium Complex, and ORIGINAL on a teal band

A white supplement carton standing on a pale gray surface against a plain gray backdrop. The front panel reads "NORDVIT" in bold black capitals at the top, "Magnesium Complex" in a smaller black sans-serif below it, and "ORIGINAL" in white capitals on a teal band across the lower third. Soft even studio light from the front left, a short soft shadow to the right. Straight-on shot at carton height, 85mm lens, the carton centered. Photoreal supplement packaging photography, cool neutral palette.

ORIGINALEXTRA STRENGTH

The instruction names which string changes and which ones stay, which matters more here than in other edits because a carton carries several pieces of text and "change the text" gives the model no way to pick. Quoting the survivors, "NORDVIT" and "Magnesium Complex", pins them as literally as the new string.

This is the practical route to a variant set. One packaging render becomes the whole product line by editing the flavor band, and the lighting and the carton geometry stay identical across the set in a way that separate generations never would.

Editing text works best when the target is visually separated from its surroundings, like the band here. Copy set over a photograph or a busy texture is harder to isolate, and the edit tends to take some of the background with it. When a frame holds several strings, identify the one you mean by its position or its container rather than by calling it the text.

Tips for best results

  1. Quote every string. Unquoted copy is a description, and the model will rewrite it into something that means the same thing.

  2. Keep strings short. A wordmark, a headline, a date line. Reliability drops with length, and body copy is where it breaks.

  3. Say how much room the text takes. "Filling two thirds of the panel width" beats "large", which has nothing to be large relative to.

  4. State sizes relative to each other. "At a quarter of that size" builds a hierarchy. Absolute point sizes mean nothing here.

  5. Write the strings in reading order. Headline, then subhead, then footer. Prompts that jump around come back with the levels swapped.

  6. Generate at the delivery tier. Small type is the first casualty of a lower tier, and there is no upscale pass to recover it.

  7. Quote the survivors when editing. Name the strings that must not change as precisely as the one that must, or the model picks for you.