Chrome extension icons 16/32/48/128 from one Sume master
Chrome's manifest icons are PNG-preferred at 16, 32, 48 and 128 px, and SVG is not supported. Make one 1:1 master on Sume and downsample it in Pillow.
Chrome's extension icon page lists four sizes: 16 x 16 for the favicon on extension pages and the context menu, 32 x 32 because Windows often needs it, 48 x 48 for the extensions management page, and 128 x 128 for installation and the Chrome Web Store. PNG is recommended, and SVG is not supported for manifest icons. One square master from Sume, downsampled four times, covers all of them.
Sizes and where they appear
At least one icon is mandatory for the toolbar, and all icons should be square. If none is supplied, Chrome generates a generic toolbar icon from the first letter of the extension name.
| Size | Used for |
|---|---|
| 16 x 16 | Favicon on extension pages, context menu icon |
| 32 x 32 | Windows computers often require this size |
| 48 x 48 | Extensions management page |
| 128 x 128 | Installation and the Chrome Web Store |
Why not an SVG from the image API
Sume's Image API lists svg among output_format values, but the Chrome page says SVG files are not supported for any manifest icons. Request png; for the Chrome extension manifest SVG is the wrong choice.
One master, four files
Generate at the square ratio, then derive the set. Resize from the master each time rather than chaining 128 to 48 to 32, so every file is one resampling step from the original. A flat, high-contrast mark survives 16 pixels; a detailed illustration will not, so judge the 16 pixel file before approving the master.
import os, io, requests
from PIL import Image
r = requests.post(
"https://api.sume.com/v1/images",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
json={"model": "openai/gpt-image-2.5", "aspect_ratio": "1:1", "prompt": "bold simple mark of a magnifying glass, flat two-color style, no text", "output_format": "png"},
timeout=90,
)
r.raise_for_status()
if r.status_code != 200:
raise SystemExit("202: read the finished job from /v1/jobs/{id}/result")
img = Image.open(io.BytesIO(requests.get(r.json()["data"][0]["url"], timeout=60).content))
master = img.convert("RGBA")
for px in (16, 32, 48, 128):
master.resize((px, px), Image.LANCZOS).save(f"icon-{px}.png", optimize=True)
print("wrote", f"icon-{px}.png")Judging the 16 pixel file
The 16 x 16 icon is where generated art fails first. Detail that looks fine at 128 pixels becomes a gray smear at 16, and Lanczos resampling cannot rescue a mark that was too busy. Judge the smallest file first, on both a light and a dark toolbar, and approve the master only if that file is still recognizable. If it is not, generate again with a prompt that asks for one bold shape, thick strokes and two colors, instead of retouching the small file by hand. The page also says all icons should be square to avoid distortion, which is why the request asks for a 1:1 ratio and the script never stretches the image. Chrome shows the first letter of the extension name when no icon is supplied, which is a useful fallback to know about but not a design to ship.
Manifest entry
Register the files under the icons key with the pixel size as the key and the file path as the value, as the page describes: "icons": {"16": "icon-16.png", "32": "icon-32.png", "48": "icon-48.png", "128": "icon-128.png"}. For the 128 size's padding rules in the store listing, see the 128 px padding post.
Sources
Related posts
More in Developers
- Chrome Web Store marquee 1400x560: crop a 21:9 Sume image
The optional marquee is 1400x560, a 5:2 ratio no Sume model lists. Generate 21:9 on FLUX.2 Pro and crop 6.7% of the height, or lose 20% from a 2:1 image.
- Claude Agent SDK 0.2.160: background wait ceiling, Sume video job
Claude Agent SDK Python 0.2.160 keeps stdin open until background subagents go idle, ten minutes by default. Why a Sume video job can outlast that.
- Claude Code 2.1.288 hooks fail closed: a Sume spend guard script
Claude Code 2.1.288 now blocks a tool call when a PreToolUse hook can't match or serialize input. A small guard script for Sume paid calls.
- allowManagedModsOnly in Claude Code: does hosted Sume MCP still load?
allowManagedModsOnly keeps users' own Claude Code mods from loading. What it leaves alone, how a policy mod reviews the rest, and the Sume MCP connection.
Written by Sume