MODEL IDmeta:muse@image
live

Muse Image

Meta
by Meta

Muse Image is Meta's flagship image generation model from Meta Superintelligence Labs. It is built for prompt-faithful image creation, precision editing, and multi-reference composition, with strong text rendering and the ability to refine existing photos through localized markup-based edits. Meta positions it as an agentic image model that plans layouts, uses search and coding tools to improve accuracy, blends multiple visual references intelligently, and handles both creative generation and practical visual tasks such as infographics, QR codes, restorations, product-style mockups, and photobomber removal.

Muse Image

Rendering exact text with Muse Image

How to render exact, legible copy inside an image with Muse Image: quoting the literal string, keeping it short, directing the type, and landing multi-element layouts.

Introduction

Baked-in copy is where generated design work usually falls apart. Most image models treat lettering as texture rather than as a string with a spelling, so an otherwise clean layout comes back with a headline that reads NEWW ARRIVALS and the file is unusable.

Muse Image takes the other route. It plans the layout before it renders anything, then refines the frame inside its own reasoning pass, which is what makes it usable for work where a misspelling is a failed deliverable. The carton below carries three separate strings at three sizes, and each one is set where the prompt put it.

This guide covers the prompt side of getting copy right: quoting the string, keeping it short, writing numbers and prices so they stay attached to the right item, directing the type, and landing layouts where several elements all have to be correct.

Quoting the copy

Wrap every string you want rendered in quotation marks. The quotes separate copy you are setting from copy you are describing. Inside them the model treats the characters as content to render. Outside them it reads a description of what a sign says and writes its own wording to fit.

The quoted decal sets both lines as written, down to the dollar sign and the month. The second prompt describes the same offer in the same scene and leaves the wording to the model, which lands somewhere near the brief rather than on it.

Give each string a role as well as a value. "reads NEW MEMBER OFFER" is weaker than "the headline across the top reads NEW MEMBER OFFER". The role tells the model what the string is for, and the layout follows from it.

import { createClient } from '@runware/sdk'

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

const [result] = await client.run({
  model: 'meta:muse@image',
  positivePrompt: 'A modern gym storefront photographed straight on from the pavement, with a large white vinyl decal applied across the window glass. The decal reads "NEW MEMBER OFFER" in heavy condensed uppercase across the top and "$0 JOINING FEE UNTIL MARCH" in a lighter weight on the line below. Racks of dumbbells and a row of treadmills are visible through the glass behind the lettering, bright overcast daylight, clean architectural photography.',
  width: 1920,
  height: 1280
})
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": "meta:muse@image",
            "positivePrompt": "A modern gym storefront photographed straight on from the pavement, with a large white vinyl decal applied across the window glass. The decal reads \"NEW MEMBER OFFER\" in heavy condensed uppercase across the top and \"$0 JOINING FEE UNTIL MARCH\" in a lighter weight on the line below. Racks of dumbbells and a row of treadmills are visible through the glass behind the lettering, bright overcast daylight, clean architectural photography.",
            "width": 1920,
            "height": 1280
        })


asyncio.run(main())
curl https://api.runware.ai/v1 \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "taskType": "imageInference",
      "taskUUID": "4c7f1a92-8d3e-4b16-9a2f-0e5b7c8d91a3",
      "model": "meta:muse@image",
      "positivePrompt": "A modern gym storefront photographed straight on from the pavement, with a large white vinyl decal applied across the window glass. The decal reads \"NEW MEMBER OFFER\" in heavy condensed uppercase across the top and \"$0 JOINING FEE UNTIL MARCH\" in a lighter weight on the line below. Racks of dumbbells and a row of treadmills are visible through the glass behind the lettering, bright overcast daylight, clean architectural photography.",
      "width": 1920,
      "height": 1280
    }
  ]'
runware run meta:muse@image \
  positivePrompt="A modern gym storefront photographed straight on from the pavement, with a large white vinyl decal applied across the window glass. The decal reads \"NEW MEMBER OFFER\" in heavy condensed uppercase across the top and \"\$0 JOINING FEE UNTIL MARCH\" in a lighter weight on the line below. Racks of dumbbells and a row of treadmills are visible through the glass behind the lettering, bright overcast daylight, clean architectural photography." \
  width=1920 \
  height=1280
{
  "taskType": "imageInference",
  "taskUUID": "4c7f1a92-8d3e-4b16-9a2f-0e5b7c8d91a3",
  "model": "meta:muse@image",
  "positivePrompt": "A modern gym storefront photographed straight on from the pavement, with a large white vinyl decal applied across the window glass. The decal reads \"NEW MEMBER OFFER\" in heavy condensed uppercase across the top and \"$0 JOINING FEE UNTIL MARCH\" in a lighter weight on the line below. Racks of dumbbells and a row of treadmills are visible through the glass behind the lettering, bright overcast daylight, clean architectural photography.",
  "width": 1920,
  "height": 1280
}
Response
[
  {
    "taskType": "imageInference",
    "taskUUID": "4c7f1a92-8d3e-4b16-9a2f-0e5b7c8d91a3",
    "imageUUID": "b8d0e6f1-3a4c-4d5e-8f90-1a2b3c4d5e6f",
    "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/b8d0e6f1-3a4c-4d5e-8f90-1a2b3c4d5e6f.jpg"
  }
]

Text-to-image calls size the frame with width and height, taken from a fixed list of eight pixel pairs. resolution: "2K" is the other way to size a request, and it applies only when you attach inputs.referenceImages, where it takes the aspect ratio from the input. The two cannot be sent in the same request.

Keeping each string short

Accuracy drops as a string gets longer. A headline, a product name, a price and a one-line qualifier are the units that render cleanly. A paragraph of body copy set inside the image is where it starts to break down.

Write the copy the way the finished piece would carry it, as set pieces rather than as a sentence:

Brief in one string
"Our new lightweight commuter tyres are now available in three widths, and fitting is free when you buy in store"

Same brief as set pieces
"COMMUTER TYRE FITTING"
"Three widths in stock"
"Fitting included in store"

The split does two jobs. Each string stays short enough to render reliably, and the hierarchy becomes explicit instead of something the model has to infer from a run-on sentence.

When a frame is finished except for one wrong word, regenerating the whole prompt trades a small error for a new layout. Send the image back with a scoped instruction instead, covered in editing images.

Numbers and prices

Write every number into the string yourself. "30% OFF" is copy. "a discount" is a decision handed to the model, and it will make one. The same holds for counts, sizes, dates and percentages, all of which come back as a plausible invented value when the prompt only implies them.

When a layout carries more than one price, keep each price inside the same quoted string as its item. A price written in its own clause is free to attach to the wrong row when the model lays the card out.

Both rows on the card are written as a single string that carries the tyre and its price together, so the $42 travels with the 35C line rather than floating between the two rows. The same pattern holds for a size next to a variant name or a serving count next to a flavour.

Type direction

Left undirected, the model picks a typeface and a position that suit the scene, and that choice moves between runs. Naming the treatment is how you get a specific look rather than a plausible one. Four directives carry most of the work:

  • Weight and case: heavy condensed uppercase, light title case, small widely letter-spaced capitals
  • Colour: white on the deep green field, charcoal on sand
  • Placement: across the lower left, centred in the upper half, along the bottom edge of the panel
  • Hierarchy: which string is the headline, which sits directly beneath it, which is the small print

All three feature graphics carry the same two strings. Weight, case, colour and placement are the only things the prompt changed, and each one reads as a different brand.

Hierarchy is set in words, not in point sizes. There is no type scale to pass, so phrases like "directly beneath it in a lighter weight" and "small capitals along the bottom edge" are the levers you have. Say which string is largest and what sits under it, and the relationship survives the layout the model plans.

A real brand's wordmark is a different problem from a string you invented. Two ways to pin one: let the model look it up with settings.imageSearch, covered in grounded generation, or attach the asset itself through inputs.referenceImages, covered in multi-reference composition.

Multi-element layouts

A real brief is rarely one string. Give each element its own clause, naming what it is, what it says and where it sits. A story ad carries a headline, a product name, a price, a shipping line and a button label, and the frame only ships if all five are right.

A vertical social story ad for an outdoor gear brand, photographed as a charcoal 32 litre hiking backpack standing on a pale concrete floor against a warm terracotta wall, with graphic type laid over the upper and lower thirds, Across the top "WEEKEND DROP" is set in heavy white uppercase, with "Trail Pack 32L" in a lighter white weight on the line beneath it, Near the bottom "$148" is set large in white, with "Free shipping over $75" in small white capitals directly under the price, A white outlined pill at the very bottom holds the words "Shop the drop", Clean commercial layout, generous margins, soft daylight
SceneHeadlineSubheadPriceSupport lineButtonStyle

Order the clauses the way the design stacks, from the top of the frame down. A prompt that already reads in the order of the finished piece leaves the planning pass less to resolve. settings.thinkingLevel defaults to high, which is the depth that planning runs at, and prompting covers when dropping it to low is worth it.

Expect the layout to reflow. Elements move between runs even when the copy holds, so treat placement as a strong preference rather than a coordinate. If something has to sit at an exact position, generate it into a clear area of the frame and place the rest downstream.

Structured layouts like data tables and functional QR codes are built by a different mechanism. The model can write and run code to lay those out before it renders, covered in infographics and charts.

Run-to-run variation

The same request run twice comes back with a different image. There is no seed parameter on this model, so a frame you like cannot be pinned and reproduced. Prompting covers what that means in general. For text it means the exact lettering and the layout both move from run to run, and a string that came out perfect once can come back with a dropped character.

The three wrappers came from one request. The copy holds across all three, and the tracking and the badge position do not.

Batch the attempt instead of perfecting the prompt. Ask for several results in one call, read them all, and keep the one whose copy is clean. That is usually faster than another round of prompt edits, because the prompt was not what was wrong.

import { createClient } from '@runware/sdk'

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

const [result] = await client.run({
  model: 'meta:muse@image',
  positivePrompt: 'A flat lay of a single protein bar wrapper on a pale grey surface, photographed straight down and filling the frame. The wrapper is deep navy with the wordmark "OATBAR" in large white uppercase across the middle, "Peanut + Sea Salt" directly beneath it in a lighter white weight, and "12 G PROTEIN" in a small white box in the lower right corner. Soft even studio light, sharp print detail on the foil.',
  numberResults: 3,
  width: 1600,
  height: 1600
})
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": "meta:muse@image",
            "positivePrompt": "A flat lay of a single protein bar wrapper on a pale grey surface, photographed straight down and filling the frame. The wrapper is deep navy with the wordmark \"OATBAR\" in large white uppercase across the middle, \"Peanut + Sea Salt\" directly beneath it in a lighter white weight, and \"12 G PROTEIN\" in a small white box in the lower right corner. Soft even studio light, sharp print detail on the foil.",
            "numberResults": 3,
            "width": 1600,
            "height": 1600
        })


asyncio.run(main())
curl https://api.runware.ai/v1 \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "taskType": "imageInference",
      "taskUUID": "9e2b4d70-5c81-4f3a-b6d9-7a0c1e2f3b45",
      "model": "meta:muse@image",
      "positivePrompt": "A flat lay of a single protein bar wrapper on a pale grey surface, photographed straight down and filling the frame. The wrapper is deep navy with the wordmark \"OATBAR\" in large white uppercase across the middle, \"Peanut + Sea Salt\" directly beneath it in a lighter white weight, and \"12 G PROTEIN\" in a small white box in the lower right corner. Soft even studio light, sharp print detail on the foil.",
      "numberResults": 3,
      "width": 1600,
      "height": 1600
    }
  ]'
runware run meta:muse@image \
  positivePrompt="A flat lay of a single protein bar wrapper on a pale grey surface, photographed straight down and filling the frame. The wrapper is deep navy with the wordmark \"OATBAR\" in large white uppercase across the middle, \"Peanut + Sea Salt\" directly beneath it in a lighter white weight, and \"12 G PROTEIN\" in a small white box in the lower right corner. Soft even studio light, sharp print detail on the foil." \
  numberResults=3 \
  width=1600 \
  height=1600
{
  "taskType": "imageInference",
  "taskUUID": "9e2b4d70-5c81-4f3a-b6d9-7a0c1e2f3b45",
  "model": "meta:muse@image",
  "positivePrompt": "A flat lay of a single protein bar wrapper on a pale grey surface, photographed straight down and filling the frame. The wrapper is deep navy with the wordmark \"OATBAR\" in large white uppercase across the middle, \"Peanut + Sea Salt\" directly beneath it in a lighter white weight, and \"12 G PROTEIN\" in a small white box in the lower right corner. Soft even studio light, sharp print detail on the foil.",
  "numberResults": 3,
  "width": 1600,
  "height": 1600
}
Response
[
  {
    "taskType": "imageInference",
    "taskUUID": "9e2b4d70-5c81-4f3a-b6d9-7a0c1e2f3b45",
    "imageUUID": "1c4e5a6b-7d8f-4901-a2b3-c4d5e6f70819",
    "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/1c4e5a6b-7d8f-4901-a2b3-c4d5e6f70819.jpg"
  },
  {
    "taskType": "imageInference",
    "taskUUID": "9e2b4d70-5c81-4f3a-b6d9-7a0c1e2f3b45",
    "imageUUID": "2d5f6b7c-8e90-4a12-b3c4-d5e6f7081920",
    "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/2d5f6b7c-8e90-4a12-b3c4-d5e6f7081920.jpg"
  },
  {
    "taskType": "imageInference",
    "taskUUID": "9e2b4d70-5c81-4f3a-b6d9-7a0c1e2f3b45",
    "imageUUID": "3e6a7c8d-9f01-4b23-c4d5-e6f708192a3b",
    "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/3e6a7c8d-9f01-4b23-c4d5-e6f708192a3b.jpg"
  }
]

Read the candidates at full resolution. A dropped character is invisible at thumbnail size and obvious at 100%. Check the small print before the headline, because the headline is the string the model gets right most often and the qualifier underneath it is where a run tends to break.

Production deliverables

Three pieces that ship with copy baked in, each generated at one of the model's eight fixed pixel pairs. Pick the pair closest to the placement and crop downstream when the target size is not one of the eight. The full list is in the model reference.

Email header banner

A campaign header is one headline over one supporting line in a frame far wider than it is tall. 2352 × 1008 is the widest of the eight pairs and crops down to a standard email header without touching the type.

The type sits in the left half and the product in the right, and both halves are named as placement in the prompt. Naming which side each element occupies is what stops a wide banner from centring everything and leaving the ends empty.

App store screenshot caption

Store screenshots carry a caption band above a device frame, and that caption is the copy a browsing customer actually reads. Give the caption and the step marker separate quoted strings, so the small marker is not absorbed into the headline.

The screen inside the phone frame is left undescribed beyond the app category. Interface text renders small and rarely survives at that size, so spend the prompt on the strings a customer reads at full size and keep the mockup generic.

Packaging insert card

An insert card is a couple of lines and a code that a customer has to type. A code is the least forgiving string in a layout, because there is no word for the model to fall back on when a character slips. Quote it in uppercase and read it back character by character before a batch goes to print.

Tips

  1. Quote every string you want set. Anything outside quotation marks is a description the model rewords. Anything inside is content it renders.

  2. Keep each string short. A headline, a product name, a price and a one-line qualifier all render reliably. Body copy at paragraph length does not.

  3. Write the number, never imply it. Put the number in the string yourself, whether it is a price, a percentage, a count or a date. Anything the model has to derive, it invents.

  4. Keep a price in the same string as its item. A price in its own clause can attach to the wrong row when the layout reflows.

  5. Name weight, case, colour and placement. Type you do not direct gets chosen for you, and the choice changes between runs.

  6. Batch, then pick. Ask for several results in one call. Lettering varies from run to run with no seed to pin it, so a batch of candidates beats one more prompt edit.

  7. Check the copy at full resolution. Errors that vanish in a thumbnail are obvious at 100%, and the small print breaks before the headline does.

  8. Fix a single wrong word by editing. Send the frame back with a scoped instruction rather than regenerating and losing a layout you already liked. See editing images.