# Testing APNs Push Notifications on the iOS Simulator

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-02. 4 min read.
> Source: https://vp0.com/blogs/testing-apns-push-notifications-mac-simulator

The modern simulator can receive push. Drag an APNs payload onto it or use simctl, and test most of your notification UI without a device.

**TL;DR.** Recent Xcode and iOS Simulator versions can receive push notifications, so you can test your notification UI without a real device. Send a test by dragging an APNs JSON file onto the simulator or using the simctl push command, with your app's bundle id. Permissions, foreground and background presentation, and deep links all work; real APNs delivery and device tokens still need hardware. Start the UI from a free VP0 design.

For years the rule was that push notifications could only be tested on a real device, which slowed down every notification feature. That rule is gone: recent versions of the iOS Simulator can receive push, so you can build and tune most of your notification UI on your Mac. VP0 is the free, AI-readable iOS design library builders start from for notification and permission screens, so you can iterate on the design fast while the simulator stands in for a device.

## Who this is for

You are building an iOS app, maybe with Cursor or Claude Code, that sends push notifications, and you want a fast local loop instead of deploying to a device for every change. This is how to test push on the simulator, and where the simulator stops.

## Two ways to send a test push

There are two simple paths, both using a tiny JSON payload with an aps object. The first is to drag the JSON file onto the running simulator window, and the notification appears. The second is the command line: xcrun simctl push with the booted device, your app bundle id, and the file path. Both deliver the payload as if it came from Apple's servers, so your [UserNotifications](https://developer.apple.com/documentation/usernotifications) handling runs exactly as it would on a device. Apple documents the broader device and simulator workflow in its [devices and simulator guide](https://developer.apple.com/documentation/xcode/devices-and-simulator).

## What works on the simulator, and what does not

The simulator covers the day-to-day work, but a few things still need hardware.

| Capability | Simulator | Real device |
| --- | --- | --- |
| Permission prompt and status | Yes | Yes |
| Foreground and background presentation | Yes | Yes |
| Tap handling and deep links | Yes | Yes |
| Real APNs delivery and device token | No | Yes |
| Live provider-to-APNs round trip | No | Yes |

So you build the entire notification experience, the permission primer, the banner, the tap that routes into the app, on the simulator, and you save the device for the live token registration described in Apple's [registering with APNs guide](https://developer.apple.com/documentation/usernotifications/registering-your-app-with-apns). If you ship with Expo, the same payload thinking maps to the [Expo push notifications](https://docs.expo.dev/push-notifications/overview/) flow.

## Keep the loop tight

Two habits make this pay off. Keep a small library of payload files, one per notification type you send, so reproducing any of them is a single simctl command rather than a fresh hand-edit each time. And do the device pass only once the simulator looks right, the same device-side step you hit in a [Cursor to TestFlight tutorial](/blogs/cursor-to-testflight-tutorial/), where signing snags like a [codesigning identity error](/blogs/xcode-codesigning-identity-error-ai-apps/) also live. About 76% of developers [now use or plan to use AI tools](https://survey.stackoverflow.co/2024/ai) to write this notification glue, and the simulator is what keeps iterating on it fast: it is the difference between checking a banner in seconds and waiting on a build, a reinstall, and a real push every single time.

## A worked example: tuning a reminder

Say you are building a reminder that should deep link to a specific screen. You write a small JSON file with an aps alert and a custom field naming the target screen. You boot the simulator, run simctl push with your bundle id and that file, and the banner slides in. You tap it, and your handler reads the custom field and routes to the screen, except it does not, because the route is wrong. On a device this would have meant a rebuild, a reinstall, and a real push each time. On the simulator you fix the handler, run the same one-line command, and see the result in seconds. You repeat until the banner copy, the badge count, and the deep link are all correct, then do a single confirmation pass on a real device for the live token and end-to-end delivery. The tight local loop turned a slow, device-bound chore into a fast iteration.

## Common mistakes and fixes

- Wrong bundle id in the command. It must match the installed app exactly.
- App never asked permission. Request authorization before expecting banners.
- Malformed aps payload. The JSON needs a valid aps object.
- Expecting a real device token. The simulator does not register live with APNs.
- Old simulator. Update Xcode so the simulator supports push.

When your notifications drive an AI feature, the same care over honesty applies, as in a [voice cloning script teleprompter](/blogs/voice-cloning-script-teleprompter-ui-ios/).

## Key takeaways

- The modern iOS Simulator can receive push for fast local testing.
- Send a payload by dragging a JSON file or using xcrun simctl push.
- Permissions, presentation, and deep links all work on the simulator.
- Real tokens and live delivery still need a device; start from a free VP0 design.

## Frequently asked questions

The FAQ above answers whether you can test push on the simulator, how to send a test, what still needs a device, and why a push might not appear.

## Frequently asked questions

### Can you test push notifications on the iOS Simulator?

Yes. Recent Xcode and iOS Simulator releases can receive push notifications, so you can test your notification UI without a device. Send a local APNs payload by dragging a JSON file onto the running simulator or with the simctl push command and your bundle id. Request permission and handle the tap exactly as on device. Start the notification UI from a free VP0 design.

### How do I send a test push to the simulator?

Create a small JSON file with an aps payload, including the alert, badge, and sound, then either drag it onto the running simulator window or run xcrun simctl push with the device id, your app bundle id, and the file. The notification appears as if it came from APNs, so you can test presentation and the tap handler immediately.

### What still needs a real device for push?

Real end-to-end APNs delivery and a real device token still need hardware, because the simulator does not register with Apple's servers the same way. Test the live token flow, background delivery under real conditions, and provider-to-APNs delivery on a device, but use the simulator for the day-to-day work of building and tuning the notification UI and tap handling.

### Why is my simulator push not appearing?

The usual causes are a missing or wrong bundle id in the payload command, the app not having been granted notification permission, a malformed aps payload, or an older simulator that does not support push. Confirm the app requested authorization, the JSON has a valid aps object, and you passed the correct booted device and bundle id to simctl.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
