Message limits

Push notification payload generator

Build a valid APNs or FCM payload from a form, watch the byte count against the 4096-byte limit, and catch the mistakes each platform rejects.

Payload
186 / 4,096 bytes5%

Measured as encoded UTF-8, the way the limit is enforced: an emoji in the body is one character and four bytes.

APNs payload
{ "orderId": "4821", "deepLink": "app://orders/4821", "aps": { "alert": { "title": "Order shipped", "body": "Your order #4821 left the warehouse and arrives Thursday." }, "sound": "default", "badge": 1 } }

Instructions

How to use this tool

  1. 01Pick the platform. The same title, body, and custom data produce structurally different JSON on APNs and FCM, which is half of what this tool exists to show.
  2. 02Fill in the title and body. Leaving both empty produces a silent or data-only payload, and the tool tells you what that means on each platform.
  3. 03Add custom data as a JSON object. On APNs it sits beside the aps dictionary; on FCM it goes under message.data, where every value must be a string.
  4. 04Watch the byte meter and copy the payload when it is green. Both platforms reject anything over 4096 bytes.

Background

The same notification, two different shapes

APNs wants a JSON object whose reserved aps dictionary holds the alert, sound, and badge, with your custom keys sitting beside it at the top level. Putting custom keys inside aps is the classic mistake: Apple reserves that dictionary, and your values are ignored rather than delivered. FCM's HTTP v1 API wraps everything in a message envelope with notification for the visible part and data for your key-value payload.

FCM adds a constraint that regularly surprises people: every value in data must be a string. A count of 3 or a flag of true that works fine in APNs custom data is rejected by FCM until it is sent as "3" or "true" and parsed back in the app.

Background

The 4096-byte limit, measured honestly

Both platforms cap the payload at 4096 bytes. APNs rejects an oversized notification at the connection, and the limit applies to the encoded JSON, so it is measured in UTF-8 bytes rather than characters: an emoji in the body is one visible character and four bytes.

The budget goes faster than expected because everything shares it: the alert text, the custom keys and their names, and the JSON punctuation itself. Deep-link URLs and serialized objects in custom data are the usual overweight passengers. If a payload is close to the limit, move data out of the notification and have the app fetch it: a push is a doorbell, not a truck.

FAQ

Frequently asked questions

What is the maximum size of a push notification payload?

4096 bytes on both APNs and FCM, measured on the encoded JSON. APNs allows 5120 bytes for VoIP pushes, which are a separate mechanism and not what this tool builds.

Where do custom keys go in an APNs payload?

At the top level of the JSON, beside the aps dictionary, never inside it. Apple reserves aps for the alert, sound, badge, and delivery flags; custom keys placed inside it are ignored.

Why does FCM reject my data payload?

Usually because a value in data is not a string. FCM's data field is a string-to-string map, so numbers, booleans, and nested objects must be serialized to strings and parsed by the app on arrival.

What happens if the payload is over the limit?

The platform rejects it and nothing is delivered. APNs returns PayloadTooLarge, and FCM returns an invalid-argument error. Neither truncates for you, which is why a builder that counts bytes before you ship beats finding out from error logs.

Send push without hand-building payloads

Courier turns one send call into correct APNs and FCM payloads, with tokens, retries, and provider failover handled for you.

Explore push notifications