Performance Max text limits: 30, 90, 90 and 25 characters, counted

Performance Max headlines run 30 characters, long headlines 90, descriptions 90, business name 25. A short script counts generated copy before upload.

4 min readSume
All posts

Performance Max asset groups accept headlines of up to 30 characters (3 to 15 of them), long headlines of up to 90 (1 to 5), descriptions of up to 90 (2 to 5) and a business name of up to 25. Count generated copy against those limits in code before you submit it, because a slot over its limit fails the format.

The text slots

The Google Ads API page on Performance Max asset requirements lists these slots. Values were read on 2026-10-03.

Performance Max text asset limits (read 2026-10-03)
SlotMax charactersHow many
Headline303 to 15
Long headline901 to 5
Description902 to 5
Business name251

Pair copy with visuals as a unit

A creative review goes faster when the copy slot and the visual that sits next to it are produced together. A batch that renders ten visuals and a separate sheet of copy invites mismatches, such as a headline that names a product color the image does not show.

One approach is to generate the visual from a structured brief and write the headline from the same brief. With Sume, a Format run item can bind an output_schema, so the run returns copy fields in a fixed shape. Bulk runs queue 1 to 100 such items with a concurrency window of 1 to 16.

A counting script

The script below checks a list of candidates against each slot and prints what to cut. It counts Python characters, so confirm how Google counts any non-Latin script or emoji in your account before relying on it for those.

LIMITS = {
    "headline": (30, 3, 15),
    "long_headline": (90, 1, 5),
    "description": (90, 2, 5),
    "business_name": (25, 1, 1),
}
def check(slot, items):
    max_len, min_n, max_n = LIMITS[slot]
    problems = []
    if not (min_n <= len(items) <= max_n):
        problems.append(f"{slot}: need {min_n}-{max_n} items, have {len(items)}")
    for text in items:
        if len(text) > max_len:
            problems.append(f"{slot}: {len(text)}/{max_len} -> {text!r}")
    return problems
copy = {
    "headline": ["Trail shoes built to grip", "Light on the foot", "Free returns for 30 days"],
    "long_headline": ["Lightweight trail running shoes with a grippy sole for wet ground"],
    "description": [
        "Cushioned, light and built for wet trails.",
        "Order today and try them for 30 days.",
    ],
    "business_name": ["Northline Outfitters"],
}

for slot, items in copy.items():
    for line in check(slot, items):
        print(line)
print("done")

Where generated copy goes wrong

Language models overshoot character limits often, and asking for a limit in the prompt does not guarantee it. Keep the check as a gate in the pipeline, not as a hope. When a line is over, rewrite it and recheck rather than truncating mid-word.

Keep claims in the copy consistent with the product the visual shows. Anything about price, discounts or shipping must match your landing page, which is a policy matter on the ad platform and not something a character counter can verify.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume