Pub-sub over plain HTTP, delivered to phones and browsers
ntfy turns a URL into a notification channel. Anything PUT or POSTed to a topic URL reaches its subscribers through the Android or iOS app, the web app, ntfy subscribe, or any HTTP client. Nothing needs creating first: a topic exists once someone publishes or subscribes to it. The public server at ntfy.sh works without an account, and the same Go server installs on your own hardware.
curl -d "Backup finished" ntfy.sh/my-topic
Headers for priority, action buttons and webhook templates
- Formatting through headers: title, priority on a 1 to 5 scale, tags shown as emojis, an icon, a click URL, and Markdown, which renders on Android and in the web app.
- Buttons on the notification: open a page or an app, fire an Android broadcast, send an HTTP request, or copy text to the clipboard.
- Scheduled delivery:
Attakes a timestamp, a duration or a phrase such astomorrow, 3pm, and has honored time zones since v2.29.0. Scheduled messages stay editable and cancellable until sent. - JSON webhooks without a bridge: built-in Go templates for
github,grafanaandalertmanagerpull a title and body out of the payload; custom ones live in/etc/ntfy/templates. - More ways in and out: publish by email, forward a notification to an inbox, or have it read aloud in a phone call to a verified number. ntfy also works as a UnifiedPush distributor, with no Firebase Cloud Messaging involved, and as a Matrix push gateway.
- Packaging: a statically linked binary for amd64, armv7 and arm64, deb and rpm packages, a Docker image and a Helm chart. Storage defaults to SQLite with no external dependency; PostgreSQL is the alternative.
Backup jobs, uptime checks and Home Assistant alerts
- Backups and cron jobs: one
curlas the script's last line, and borgmatic is on the project's list of official integrations. - Monitoring: Uptime Kuma, Gatus and Healthchecks.io are on that list too, as is Home Assistant for home automation.
- Grafana and Alertmanager alerts, or GitHub events, formatted by the built-in templates.
Open by default, and iOS still routes through ntfy.sh
An unconfigured server lets anyone in. ntfy serve listens on port 80 without a config file, and anyone can then read and write any topic. Messages sit in memory for 12 hours and vanish on restart. Locking an instance down takes a user database (auth-file or database-url) plus auth-default-access: deny-all. Every topic on ntfy.sh is public, so without ACLs the topic name is the password.
iPhones tie a self-hosted server back to ntfy.sh. Because iOS restricts background work, instant delivery needs a relay: your server sends ntfy.sh (upstream-base-url) the message ID and a SHA-256 hash of the topic URL, ntfy.sh hands that to Firebase and APNs, and the phone then fetches the message from your server. Without the relay, the docs warn, delivery can take hours. Android has no such dependency: for any server other than ntfy.sh, the app keeps a connection open.
Free use of ntfy.sh stops at 250 messages a day, with a 2 MB attachment limit. Paid plans start at $5 a month, and the entry plan, Supporter, allows 2,500 messages a day. The FAQ aims them at people who would rather not self-host or need higher limits; the code stays dual-licensed under Apache 2.0 and GPLv2, Stripe billing included.
v2.34.0, released on October 24, 2026, is the current version, the eighth tagged that month. Most of those releases build toward clustering on a shared PostgreSQL database, which the docs call experimental and "not ready for production". v2.31.0 fixed messages lost when a client reconnects: in load tests with restarts and crashes, losses fell from 465 to 2 out of about 615,000 messages.
