Google Play screenshots: 9:16 at 1080x1920, side limit 2x
Play screenshots need 320 to 3840 px and a long side at most twice the short side. Four 1080 x 1920 9:16 shots also meet the promo eligibility note on the page.

Google Play screenshots are JPEG or 24-bit PNG with no alpha, between 320 and 3840 pixels per side, and the long side cannot be more than twice the short side. For the promotional formats the page names, an app should supply at least four screenshots of 1080 pixels minimum in 16:9 or 9:16. A 1080 x 1920 portrait frame is 9:16 and passes both.
What the page requires
The ratio rule matters more than the pixel range. A 1080 x 2400 phone capture is 2.22 times as long as wide, and fails the "no more than twice" test, while 1080 x 2160 is exactly twice and passes.
| Rule | Value |
|---|---|
| Format | JPEG or 24-bit PNG, no alpha |
| Minimum side | 320 px |
| Maximum side | 3840 px |
| Long side vs short side | At most 2x |
| Promo eligibility | At least 4 shots, 1080 px minimum, 16:9 or 9:16 |
Where an image model helps
Screenshots should show your real interface, and a generated image is not one. An image model is useful for the background or device-scene a screenshot sits on, for marketing-style frames that wrap a real capture, and for illustrations in the frame caption area. Compose the real capture over the generated background locally, so the UI pixels stay exact.
On Sume, ask for aspect_ratio: "9:16", which the catalog lists for the common image families. A 9:16 source can be resized to 1080 x 1920 without cropping.
Compose and flatten
The script generates a 9:16 background, resizes to 1080 x 1920, and saves a no-alpha JPEG. convert("RGB") drops any alpha channel, which Play rejects on screenshots.
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": "bytedance-seed/seedream-4.5", "aspect_ratio": "9:16", "prompt": "soft abstract gradient backdrop in teal and cream, no text"},
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))
bg = img.convert("RGB").resize((1080, 1920), Image.LANCZOS)
w, h = bg.size
assert max(w, h) <= 2 * min(w, h) and 320 <= min(w, h) and max(w, h) <= 3840
bg.save("play-shot-bg.jpg", "JPEG", quality=90)Checking the ratio rule in code
The rule that trips people is the one about the long side being at most twice the short side. Modern phone captures are often taller than 2:1, so a raw device screenshot can fail even though each dimension is inside 320 to 3840. The script above asserts the rule before saving; do the same for real captures and crop or pad them to fit. For the promotional formats, the page asks for at least four screenshots of at least 1080 pixels in 16:9 or 9:16, so make the whole set one orientation and one size. A 1080 x 1920 file is exactly 9:16. Mixing portrait and landscape in one set is allowed by the basic rules but is harder to design for. When you flatten, remember that Play requires no alpha on screenshots, so convert to RGB before saving, as the script does.
Notes
The Image API returns Sume-hosted signed URLs in data[].url, so download the file before you rely on it. The response usage.cost is the billed amount for the request.
Play's page gives no file-size limit for screenshots, but a 1080 x 1920 JPEG at quality 90 is a modest file, and you can verify the byte count in the same script.
Sources
Related posts
More in Developers
- Goose 1.52 recipe consent before extensions: a Sume MCP recipe
Goose 1.52 asks for recipe consent before session/new spawns extensions, and caps recipe size. What to put in a recipe that uses Sume's MCP server.
- got maxRetryAfter and 429: rate_limited vs queue_full on Sume
got retries 429 and honors Retry-After up to maxRetryAfter. Sume sends 429 for rate_limited and for queue_full, which need different waits. Here is the split.
- got does not retry POST by default: enable it safely with Sume
got retries GET, PUT and DELETE but not POST. To retry a Sume paid submit, add POST to retry.methods and send one Idempotency-Key reused on every attempt.
- GPT-6.1 Sol rate limits (Tier 1: 500 RPM) vs a Sume bulk run window
OpenAI lists GPT-6.1 Sol limits from 500 RPM at Tier 1 to 15,000 RPM at Tier 5. A Sume bulk run uses a concurrency window of 1-16 and 100 items.
Written by Sume