macOS App Icon Generator
Overview
Build a macOS .icns app icon from one source image (SVG or PNG), and wire it
into an app. A .icns file packs all ten required icon sizes (16px through
1024px, @1x and @2x) into the single artifact macOS expects in an app bundle.
Prerequisites
- macOS with
qlmanage,sips,iconutil, andfile— all ship with the OS, nothing to install. - A square source image: SVG, or PNG at least 1024x1024.
Instructions
Quick start — run the bundled script:
scripts/make_icns.sh <input-image> <output.icns>
The script:
- Validates required tools (
sips,iconutil,file) and the input file. - If input is
.svg, renders it to a 1024px PNG viaqlmanage. - If input is
.png, uses it directly (warns if smaller than 1024px or non-square). - Generates all required sizes into a temp
.iconsetfolder. - Compiles the
.iconsetinto.icnsviaiconutil. - Cleans up the temp folder and prints the final
fileoutput to confirm validity.
Run it with no args (or -h) for usage help.
Examples
# SVG source, output next to it
scripts/make_icns.sh AppIcon.svg AppIcon.icns
# 1024px PNG source, output into a build directory
scripts/make_icns.sh artwork_1024.png build/AppIcon.icns
Output
A valid .icns file at the path you specified, confirmed by file reporting
Mac OS X icon. Intermediate .iconset folders are cleaned up automatically.
Wire the result into an app via the sections below.
Manual workflow (no script)
If you need to do this by hand or the script is unavailable, run the exact commands below.
1. Get a 1024x1024 PNG.
From SVG:
qlmanage -t -s 1024 -o /tmp/icon_render AppIcon.svg
# writes /tmp/icon_render/AppIcon.svg.png
From an existing PNG >= 1024px, just use it as-is.
2. Create the iconset folder and generate every required size:
mkdir icon.iconset
SRC=source_1024.png
sips -z 16 16 "$SRC" --out icon.iconset/icon_16x16.png
sips -z 32 32 "$SRC" --out icon.iconset/icon_16x16@2x.png
sips -z 32 32 "$SRC" --out icon.iconset/icon_32x32.png
sips -z 64 64 "$SRC" --out icon.iconset/icon_32x32@2x.png
sips -z 128 128 "$SRC" --out icon.iconset/icon_128x128.png
sips -z 256 256 "$SRC" --out icon.iconset/icon_128x128@2x.png
sips -z 256 256 "$SRC" --out icon.iconset/icon_256x256.png
sips -z 512 512 "$SRC" --out icon.iconset/icon_256x256@2x.png
sips -z 512 512 "$SRC" --out icon.iconset/icon_512x512.png
sips -z 1024 1024 "$SRC" --out icon.iconset/icon_512x512@2x.png
3. Compile to .icns:
iconutil -c icns icon.iconset -o AppIcon.icns
rm -rf icon.iconset
4. Verify:
file AppIcon.icns
# expect: "AppIcon.icns: Mac OS X icon, ..."
Design guidance
- Source artwork should be square. macOS renders icons inside a rounded-rect "squircle" mask automatically for most contexts — do not pre-mask/round the corners yourself, or you'll get double-masking artifacts.
- Leave roughly a 10% transparent margin around the visual content (i.e. the drawn artwork occupies about the center 80–90% of the 1024x1024 canvas). Icons that bleed to the edge look oversized next to system icons.
- Prefer a source >= 1024x1024 so the largest size (
icon_512x512@2x.png, itself 1024x1024) isn't upscaled. - Flatten the SVG (embed/inline any linked images, fonts, or
<use href>external refs) before rendering — see Edge Cases below.
Wiring the icon into an app
Xcode asset catalog (typical app target):
- Open
Assets.xcassetsin Xcode, add an "App Icon" image set (or use the existingAppIconset already scaffolded by most templates). - Drag
AppIcon.icnsonto the asset slot — Xcode auto-extracts the sizes it needs (modern Xcode also accepts a single 1024px PNG directly instead of an.icns, via the "single size" App Icon set style). - Ensure the target's Build Settings > "Asset Catalog App Icon Set Name" is
set to that asset set's name (default
AppIcon).
Raw bundle (no Xcode asset catalog, e.g. a hand-built .app or a CLI-built
bundle):
- Copy
AppIcon.icnsintoYourApp.app/Contents/Resources/. - In
Contents/Info.plist, set:
(Omit the<key>CFBundleIconFile</key> <string>AppIcon</string>.icnsextension —CFBundleIconFileimplies it. Filename must match exactly, case-sensitive.) - Re-sign/re-bundle as needed, then refresh the icon cache (see Edge Cases).
Menu bar / status bar icons are NOT the .icns
Menu bar (NSStatusItem) icons are a completely separate asset from the app
icon:
- They should be small template images (typically 18x18pt @1x/@2x/@3x, or an SF Symbol), rendered in monochrome and automatically tinted/inverted by the system for light/dark mode and selection states.
- Set
image.isTemplate = trueon theNSImage(or use an asset catalog image marked "Render As: Template Image"). - Prefer an SF Symbol (
NSImage(systemSymbolName:accessibilityDescription:)) when a suitable one exists — it inherits correct weight/scale for free. - Do not hand it a full-color, multi-size
.icns— it will not adapt to dark mode or menu bar height and will look out of place next to system icons.
Edge cases
- Non-square source.
sips -z H Wscales width/height independently, so a non-square source gets stretched/distorted. Pad to a square canvas first (e.g. in the design tool, or viasips --padToHeightWidth) rather than feeding it directly. - Source smaller than 1024px. The largest iconset entries (512, 512@2x = 1024px) will be upscaled and look soft. Get a bigger source, or accept the blur if the icon is only ever shown small.
- SVG with external references renders blank.
qlmanage's QuickLook renderer runs sandboxed and often cannot resolve<image href="...">, external fonts, or<use xlink:href="external.svg#id">. Symptom: the rendered PNG is fully transparent/blank even though the SVG looks correct in a browser. Fix: inline/flatten all external references in the SVG (or export a PNG directly from the design tool — Figma/Illustrator/Sketch "Export as PNG @1024px" — and skipqlmanageentirely). - Icon doesn't update after replacing it (Gatekeeper / icon cache).
macOS aggressively caches app icons. After swapping
AppIcon.icnsor rebuilding an unsigned/dev app:
For unsigned/ad-hoc-signed builds during development, a full re-copy of thetouch YourApp.app killall Finder # if still stale: qlmanage -r cache killall Dock.appto a new path (ormvit) often forces Finder to re-read the icon rather than reuse a cached one keyed by the old inode/path. Do not delete system cache directories under/Library/Cachesto force a refresh; the steps above are enough, and a stale icon is cosmetic. - iconutil fails with "not a valid iconset." Usually means a required
filename is missing or misnamed (must exactly match
icon_16x16.png,icon_16x16@2x.png, ...icon_512x512@2x.png) or the folder isn't named*.iconset. Re-check thelsoutput against the size list above. filedoesn't show "Mac OS X icon." Iffile AppIcon.icnsdoesn't report it as an icon,iconutilsilently wrote something else or failed — re-run with a fresh iconset folder rather than reusing a partially-built one.
Resources
scripts/make_icns.sh— the end-to-end generator described above.- Apple HIG: App icons — sizing, margins, and squircle guidance.
- Apple docs:
iconutil— iconset naming requirements.