Custom sticker and emoji packs are everywhere – messaging apps, product branding, community Discord servers. Designing them by hand takes hours per asset. Stable Diffusion can generate an entire pack in minutes, and with the right prompt structure and post-processing pipeline, the results are production-ready. Here’s how to set up the full workflow from generation to transparent PNGs sized for every major platform.

Start by installing the core dependencies:

1
pip install diffusers transformers accelerate torch rembg pillow

Generating Sticker-Style Images

The key to good sticker output is prompt engineering. Stickers need bold outlines, simple shapes, flat colors, and a clean background you can remove later. SDXL handles this well when you tell it exactly what visual style you want.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import torch
from diffusers import StableDiffusionXLPipeline

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = pipe.to("cuda")

subject = "a happy orange cat waving"

prompt = (
    f"sticker design of {subject}, bold black outline, flat colors, "
    "simple shapes, chibi style, centered on solid white background, "
    "no shadows, vector art style, die-cut sticker"
)

negative_prompt = (
    "photorealistic, complex background, gradient, blurry, "
    "3d render, shadow, text, watermark, noise"
)

image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    num_inference_steps=30,
    guidance_scale=7.5,
    width=1024,
    height=1024,
).images[0]

image.save("cat_sticker_raw.png")

A few things to note about the prompt structure. The phrase “die-cut sticker” pushes the model toward that characteristic sticker look with a visible border. Requesting “solid white background” makes background removal trivial in the next step. The negative prompt keeps the output flat and clean – you don’t want photorealism or complex lighting in a sticker.

Tuning the Style

Play with these prompt modifiers to shift the aesthetic:

  • Kawaii style: Add “kawaii, cute, japanese sticker style”
  • Cartoon bold: Add “thick outline, saturday morning cartoon”
  • Minimal/geometric: Add “geometric, minimalist, flat design”
  • Retro: Add “90s sticker, glossy, retro illustration”

Guidance scale matters here. Values between 7 and 9 keep the output faithful to sticker aesthetics. Go below 6 and you lose the clean lines. Go above 12 and you get over-saturated, artifact-heavy results.

Removing Backgrounds for Transparent PNGs

A sticker with a white background isn’t a sticker – it needs transparency. The rembg library uses the U2-Net model to strip backgrounds cleanly, and it handles the bold-outline sticker style particularly well since the subject-background boundary is sharp.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from rembg import remove
from PIL import Image
import io

input_image = Image.open("cat_sticker_raw.png")

output_image = remove(
    input_image,
    alpha_matting=True,
    alpha_matting_foreground_threshold=240,
    alpha_matting_background_threshold=10,
    alpha_matting_erode_size=10,
)

output_image.save("cat_sticker_transparent.png", format="PNG")

The alpha_matting parameters fine-tune edge quality. The foreground threshold at 240 keeps nearly-white edge pixels from bleeding into the transparent area. The erode size trims a thin border of leftover background pixels. For stickers with bold outlines, these defaults work well. If you’re generating softer styles without outlines, drop alpha_matting_erode_size to 5 or lower.

Building a Sticker Pack Generator

A single sticker is nice. A matching pack of 10-20 is what you actually need. The trick is keeping the style prefix identical across all subjects so the pack looks cohesive.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import torch
from diffusers import StableDiffusionXLPipeline
from rembg import remove
from PIL import Image
from pathlib import Path

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = pipe.to("cuda")

style_prefix = (
    "sticker design, bold black outline, flat colors, chibi style, "
    "centered on solid white background, no shadows, die-cut sticker, "
    "vector art style"
)

negative_prompt = (
    "photorealistic, complex background, gradient, blurry, "
    "3d render, shadow, text, watermark, noise"
)

subjects = [
    "a happy orange cat waving",
    "a sleeping orange cat curled up",
    "an orange cat giving a thumbs up",
    "a surprised orange cat with wide eyes",
    "an orange cat wearing sunglasses",
    "an angry orange cat with puffed fur",
    "an orange cat eating a fish",
    "an orange cat holding a heart",
]

output_dir = Path("sticker_pack")
output_dir.mkdir(exist_ok=True)

generator = torch.Generator(device="cuda").manual_seed(42)

for i, subject in enumerate(subjects):
    prompt = f"{style_prefix}, {subject}"

    image = pipe(
        prompt=prompt,
        negative_prompt=negative_prompt,
        num_inference_steps=30,
        guidance_scale=7.5,
        width=1024,
        height=1024,
        generator=generator,
    ).images[0]

    transparent = remove(image)
    transparent.save(output_dir / f"sticker_{i:02d}.png", format="PNG")
    print(f"Generated sticker {i + 1}/{len(subjects)}: {subject}")

print(f"Pack complete: {len(subjects)} stickers saved to {output_dir}")

Using a fixed seed with torch.Generator helps with reproducibility, though style consistency comes mostly from the shared prefix. If one sticker in the batch looks off, regenerate just that one with a different seed while keeping the same prefix.

Emoji vs. Sticker Differences

Emoji need to read at tiny sizes. For emoji generation, adjust the prompt:

  • Replace “sticker design” with “emoji icon”
  • Add “extremely simple, minimal detail, bold expression”
  • Drop “die-cut sticker” since emoji don’t have that outline style
  • Use fewer colors: add “limited color palette, 3-4 colors max”

Resizing and Formatting for Platforms

Each platform has different requirements for sticker and emoji assets. Here’s a utility that takes your generated stickers and outputs correctly sized versions for the three major platforms.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from PIL import Image
from pathlib import Path

PLATFORM_SPECS = {
    "imessage": {"size": (300, 300), "max_kb": 500, "format": "PNG"},
    "telegram": {"size": (512, 512), "max_kb": 512, "format": "PNG"},
    "discord": {"size": (128, 128), "max_kb": 256, "format": "PNG"},
}


def resize_sticker(input_path: str, output_dir: str, platforms: list[str] | None = None):
    """Resize a transparent sticker PNG for target platforms."""
    if platforms is None:
        platforms = list(PLATFORM_SPECS.keys())

    img = Image.open(input_path).convert("RGBA")
    out = Path(output_dir)
    stem = Path(input_path).stem

    for platform in platforms:
        spec = PLATFORM_SPECS[platform]
        target_size = spec["size"]

        resized = img.copy()
        resized.thumbnail(target_size, Image.LANCZOS)

        canvas = Image.new("RGBA", target_size, (0, 0, 0, 0))
        offset_x = (target_size[0] - resized.width) // 2
        offset_y = (target_size[1] - resized.height) // 2
        canvas.paste(resized, (offset_x, offset_y))

        platform_dir = out / platform
        platform_dir.mkdir(parents=True, exist_ok=True)
        output_path = platform_dir / f"{stem}.png"
        canvas.save(output_path, format="PNG", optimize=True)
        print(f"Saved {platform}: {output_path} ({target_size[0]}x{target_size[1]})")


# Process all stickers in a pack
sticker_dir = Path("sticker_pack")
for sticker_file in sorted(sticker_dir.glob("*.png")):
    resize_sticker(str(sticker_file), "sticker_pack_sized")

This centers the sticker on a transparent canvas at the target resolution. The thumbnail method preserves aspect ratio so nothing gets distorted. For iMessage, Apple also accepts APNG for animated stickers – that’s a different pipeline but the sizing logic is the same.

Platform-Specific Notes

  • iMessage: Sticker packs need exactly 300x300 for small, 408x408 for medium, or 618x618 for large. Apple requires Xcode to package them into a .stickerpacks bundle.
  • Telegram: 512x512 is the standard. One side must be exactly 512px, the other can be smaller. Animated stickers use TGS format (Lottie-based).
  • Discord: Custom emoji max out at 128x128 and 256KB. Stickers are 320x320 with a 500KB limit.

Common Errors and Fixes

CUDA out of memory when generating at 1024x1024:

1
torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 2.00 GiB

SDXL needs around 8GB VRAM at fp16. If you’re on a smaller GPU, enable attention slicing and VAE tiling:

1
2
pipe.enable_attention_slicing()
pipe.enable_vae_tiling()

Or drop to 768x768 generation and upscale afterward. The sticker style is forgiving at lower resolutions since it’s already simple shapes.

rembg produces jagged edges on soft-style stickers:

1
Warning: alpha_matting failed, falling back to simple mask

This happens when the foreground-background contrast is too low. Make sure your generation prompt includes “solid white background” and increase the contrast between subject and background. You can also try the isnet-general-use model instead of the default:

1
output_image = remove(input_image, session=new_session("isnet-general-use"))

Inconsistent style across a sticker pack:

If stickers in a batch look like they belong to different packs, the issue is usually prompt drift. Lock down every style descriptor in the shared prefix and only vary the subject. Avoid adding style words in the subject portion (e.g., don’t write “a watercolor cat” when your prefix says “flat colors”). Also consider using a fixed seed across the batch or a LoRA trained on a specific sticker style for maximum consistency.