Free App Store & Google Play screenshot generator that runs entirely in your browser.
No signup. No upload. No watermark. No backend.
Upload the raw screenshots you already took from the simulator, add a device frame and a headline, and download store-ready PNGs at the exact size Apple and Google require.
Most screenshot generators want an account before they'll show you anything, watermark the free tier, or upload your unreleased app designs to someone else's server. AppShot has no backend at all — there is nothing to sign up for and nowhere for your images to go.
| AppShot | Typical alternatives | |
|---|---|---|
| Account required | Never | Usually, before you can export |
| Your images | Stay in your browser | Uploaded to their servers |
| Watermark | None | Common on free tiers |
| Cost | Free, no tiers | Freemium or subscription |
| Export sizes | Exact, verified | Usually correct |
| Alpha channel | Stripped (see below) | Often left in — App Store rejects these |
| Offline | Works after first load | No |
- 26 device frames — iPhone 8 Plus through iPhone 16 Pro Max, iPad Air/Pro, Pixel, Galaxy and Surface. Drawn with canvas primitives, so there are no mockup image assets to download and "clay" frames can be recoloured.
- Multi-size export — select as many devices as you need; one download gives you a ZIP with a folder per size. Presets cover exactly what each store requires.
- 7 templates — Simple, Bold, Angled, Duo, Spotlight, Minimal and Full Bleed.
- Edit text on the screenshot — click the headline directly on the preview and type. Headlines auto-shrink to fit; subheadlines are optional per screen.
- Pixel-exact PNGs with no alpha channel — the single most common cause of App Store rejections, handled properly (see How it works).
- Your work persists — settings and text in
localStorage, images in IndexedDB. Close the tab and come back.
![]() Templates preview your actual screenshot, not stock art. |
![]() Pick several sizes at once; presets match store requirements. |
git clone https://github.com/YOUR_USERNAME/appshot.git
cd appshot
npm install
npm run devOpen http://localhost:5173.
npm run build # typecheck, bundle, prerender all routes, emit sitemap + robots
npm run preview # serve the production build locallyRequires Node 18+.
Three decisions carry most of the design.
renderSlide(canvas, slide, settings, image, scale) draws everything in export
coordinates and applies ctx.setTransform(scale, 0, 0, scale, 0, 0). The preview calls
it at ~0.22, the export calls it at 1, and template thumbnails call it at 0.055.
This is why the download always matches the preview exactly. Building the preview in
HTML/CSS and screenshotting it with html2canvas is the usual approach, and the usual
source of exports that don't look like what the user saw.
canvas.toBlob('image/png') always writes colour type 6 (RGBA), even when every pixel is
opaque. App Store Connect rejects those with "Images can't contain alpha channels or
transparencies" — after accepting the upload, so you only find out at the end.
src/lib/png.ts encodes colour type 2 (truecolour RGB) directly: read the pixels, drop the
alpha byte, Paeth-filter the scanlines, deflate with the native CompressionStream. No
library needed, and the files come out smaller than Chrome's encoder produces.
python3 -c "from PIL import Image; print(Image.open('screenshot.png').mode)"
# RGB ← what the stores accept
# RGBA ← what gets rejectedEvery frame is rounded rectangles, a notch/island/punch-hole and a home indicator, sized as
fractions of the screen width. Adding a device is a single entry in
src/data/devices.ts — no artwork, no licensing questions, and
"clay" variants are just a different fill.
npm run build renders every route to static HTML with its own title, description,
canonical URL and JSON-LD, then hydrates in the browser. Crawlers get full content without
executing JavaScript; sitemap.xml and robots.txt are generated from the same route
table so they can't drift.
src/
├── lib/
│ ├── render.ts the single render function — the heart of the app
│ ├── png.ts alpha-free PNG encoder (colour type 2)
│ ├── export.ts single PNG and multi-device ZIP export
│ ├── site.ts routes + SEO metadata (one source of truth)
│ ├── router.tsx ~60-line history router
│ ├── storage.ts localStorage project persistence
│ └── imageCache.ts IndexedDB blobs + decoded ImageBitmap cache
├── data/
│ ├── devices.ts 26 devices + store presets
│ └── templates.ts 7 template layouts
├── components/ Landing, Editor, pickers, marketing pages
└── entry-server.tsx SSR entry used by the prerender step
scripts/prerender.mjs static HTML + sitemap + robots generation
deploy/nginx.conf production server block
All 26 devices and their export sizes
Export size is the PNG dimension each store expects — not necessarily the device's real screen resolution. Every Android device exports at 1080 × 1920 because that is Google Play's standard phone screenshot canvas.
| Device | Group | Export size |
|---|---|---|
| Google Pixel 4 | Android | 1080 × 1920 |
| Google Pixel 8 Pro | Android | 1080 × 1920 |
| Google Pixel 8 Pro (clay) | Android | 1080 × 1920 |
| Google Pixel 9 Pro | Android | 1080 × 1920 |
| Google Pixel 9 Pro (clay) | Android | 1080 × 1920 |
| Samsung Galaxy S10 | Android | 1080 × 1920 |
| Samsung Galaxy S20 | Android | 1080 × 1920 |
| Surface Pro | Android | 1080 × 1920 |
| iPhone 8 Plus | iPhone | 1242 × 2208 |
| iPhone 11 | iPhone | 828 × 1792 |
| iPhone 11 (clay, thin) | iPhone | 1170 × 2532 |
| iPhone 12 | iPhone | 1170 × 2532 |
| iPhone 12 (no notch) | iPhone | 1170 × 2532 |
| iPhone 13 Pro | iPhone | 1170 × 2532 |
| iPhone 13 Pro Max | iPhone | 1284 × 2778 |
| iPhone 14 Pro | iPhone | 1290 × 2796 |
| iPhone 14 Pro (clay) | iPhone | 1290 × 2796 |
| iPhone 15 Pro Max | iPhone | 1290 × 2796 |
| iPhone 15 Pro Max (clay) | iPhone | 1290 × 2796 |
| iPhone 16 Pro Max | iPhone | 1320 × 2868 |
| iPhone 16 Pro Max (clay) | iPhone | 1320 × 2868 |
| iPad Air 3rd Gen | iPad | 1668 × 2224 |
| iPad Pro 3rd Gen | iPad | 2048 × 2732 |
| iPad Pro 3rd Gen (clay) | iPad | 2048 × 2732 |
| iPad Pro M4 | iPad | 2064 × 2752 |
| iPad Pro M4 (clay) | iPad | 2064 × 2752 |
There is also a plain-English reference at /app-store-screenshot-sizes.
Static output — any host that serves files will do. A production nginx server block with
clean URLs, caching and security headers is in deploy/.
npm run build
rsync -avz --delete dist/ user@server:/var/www/appshot/If you fork this for your own domain, change SITE_URL in
src/lib/site.ts — canonicals, Open Graph tags, sitemap.xml and
robots.txt all derive from it.
React 18 · TypeScript · Vite · Tailwind CSS · Canvas 2D
Runtime dependencies: react, react-dom, jszip, idb-keyval. That's the whole list —
the router, the PNG encoder and the device frames are all in-repo, which keeps the bundle
around 100 KB gzipped.
Contributions especially welcome on these:
- Themed template packs — coordinated background, type and device treatment as one preset
- Render exports in a Web Worker (large iPad batches currently block the main thread)
- Filmstrip editing — see and edit all screens side by side
- Localisation: one project, several languages, exported per locale
- Import/export project as JSON, to carry work between machines without an account
- Background image and gradient-mesh options
Issues and pull requests are welcome — see CONTRIBUTING.md.
Adding a device is usually a one-line change in src/data/devices.ts, and a template is a
small layout function in src/data/templates.ts. Both are good first contributions.
Not affiliated with, endorsed by, or associated with Apple Inc. or Google LLC. "App Store" and "Google Play" are trademarks of their respective owners. Device frames are generic representations, not reproductions of any manufacturer's artwork.


