Community

Apps

Zapper

Zapper is the small payment surface you open when a Nostr event, profile or addressable object needs a zap, a private-looking anonymous zap, a plain Lightning tip or a split across many recipients. Its useful power is narrow: it turns a Nostr target into one or more LNURL invoices, then lets you pay with WebLN, Bitcoin Connect or a manual invoice flow.

Zapper visual
Zapper icon
Apps The product layer Clients, signers, publishing tools, wallets and useful experiments.
Back to Nostr
Apps

Apps shelf

Apps pages collect clients, signers, tools, developer libraries and product research without turning the app into the whole network.

Apps22 min readNostr zap micro-app, split zaps, NIP-57, WebLN, Bitcoin Connect, NWC context, invoice fallback and sender-side payment checks

Zapper

Zapper is the small payment surface you open when a Nostr event, profile or addressable object needs a zap, a private-looking anonymous zap, a plain Lightning tip or a split across many recipients. Its useful power is narrow: it turns a Nostr target into one or more LNURL invoices, then lets you pay with WebLN, Bitcoin Connect or a manual invoice flow.

The quick readZapper is a live micro-app at `zapper.fun` with the title `Zapper - send tips to any event on Nostr` and the description `Zapper is a micro-app for sending zaps and LN tips on Nostr`. The official README calls it a micro-app for zapping any Nostr event and says other apps can integrate it by redirecting to `/zap` with query parameters such as `id`, `amount`, `comment`, `type` and `auto_send`. The code accepts `npub`, `nprofile`, `note`, `nevent`, `naddr` and `nrelay` bech32 shapes, though relay targets are still rejected in the current loader. It reads target events, detects `zap` tags for split zaps, loads recipient metadata, creates kind 9734 zap requests, and then fetches LNURL invoices from `lud16` or `lud06` metadata. Normal zaps require a NIP-07-style signer through `window.nostr`; anonymous zaps are signed with a generated one-time key; `send-sats` skips the Nostr zap event. Payment can happen through WebLN and Bitcoin Connect, with QR, copy and `lightning:` fallback when a wallet is not connected. The important boundary: Zapper is not a wallet, not a relay and not a full social app. It is a sender-side payment tool, so verify the target, recipient list, amount, wallet connection and invoice before you let it move sats.

What Zapper really is

Zapper is a focused Nostr payment micro-app. The live site says it sends tips to any event on Nostr, and the repository README defines it as a micro-app for zapping any Nostr event. That is the right starting point. Zapper is not trying to be your timeline, profile editor, relay manager or wallet dashboard. It is the narrow surface you open when you already have a Nostr target and want to send value to it.

The current public app lives at `zapper.fun`, with a mirror at `zapper.nostrapps.org`. Its product shape is intentionally small: landing page, about page and `/zap`. The `/zap` route is the important one. It accepts a bech32 identifier, resolves the Nostr target, builds one or more zap/payment objects, and then walks the sender through paying them. A small app can be serious when the money path is clear.

That small scope is also why Zapper belongs in the general apps map rather than only in a wallet shelf. It touches wallets because it asks a wallet or WebLN provider to pay an invoice. It touches Nostr because it reads events, profiles and tags, and because normal zaps are NIP-57 events. But Zapper itself is neither the wallet that holds funds nor the relay that stores social data.

For a reader, the useful question is not whether Zapper is famous. The useful question is whether it shows the target, recipients, amount and invoice path clearly enough before money moves. If it does, it can save you from hunting for client-specific zap buttons. If it does not, you should stop and verify the Nostr object and wallet connection somewhere else.

The actual user flow

The README documents the integration flow directly. Another app can redirect a user to `/zap` and add query parameters. The required parameter is `id`, and it can carry a bech32 Nostr identifier. Optional parameters include `amount`, `comment`, `type` and `auto_send`. That means Zapper can act like a payment handoff screen. A social app, publishing tool or split-zap product can send the user there instead of building its own zap UI.

When you arrive at `/zap`, the app reads the target, loads the relevant Nostr data, fills the amount and comment if the URL supplied them, and then shows a payment form. The type tab changes the meaning of the payment. The default code path currently starts anonymous until login state changes, while URL parameters can request a normal zap, an anonymous zap or a plain send-sats payment.

After the sender submits, the app works through each recipient. If WebLN is available, it can send through the connected provider. If WebLN is not available, it shows the Lightning invoice, a copy button, a QR option and an `Open Wallet` link using a `lightning:` URI. That fallback matters because a zap tool should not become useless when a browser extension is missing.

Zapper also keeps visible status. The modal can show that it is fetching an invoice, sending sats, waiting for manual payment or reporting an error. For split zaps, the modal title can show progress such as sending one recipient out of several. That is ordinary interface detail, but ordinary detail matters when a single action may become many payments.

How target lookup works

The target loader is the part of the code that tells you what Zapper can really handle. It uses `nostr-tools` to decode NIP-19 identifiers. An `npub` becomes a direct profile target. An `nprofile` adds its relay hints. A `note` becomes an event id. An `nevent` adds event relay hints. An `naddr` becomes an addressable-event coordinate made of kind, pubkey and identifier. The current code recognizes `nrelay`, but then rejects relay targets as not supported yet.

That distinction prevents overclaiming. Zapper can be pointed at profiles, notes, event references and addressable objects. It is not currently a general relay payment tool. If you pass an event target, the app fetches the event through NDK, using the relay hints it has and a Nostr.Band relay default. If it cannot fetch by id or address, the flow stops with an error rather than pretending the target is valid.

If the target is a profile, the recipient is straightforward: the profile pubkey gets the payment weight. If the target is an event, Zapper needs to decide who receives the money. Without split tags, it falls back to the event author. With split tags, it treats the tagged pubkeys as recipients. That behavior is why it can zap events beyond what a particular social client supports.

You should still verify the target before paying. Bech32 strings are human-unfriendly, and an `nevent` can point to a different event than the one a page visually suggested. Addressable events can be updated or referenced by coordinates that are not obvious to a casual user. Zapper can decode and fetch; it cannot know whether the object is the one you meant to reward.

Zap splits are the main trick

The most distinctive Zapper behavior is split-zap support. The loader inspects the target event for tags named `zap`. Each tag can include a pubkey, a relay and a weight. Zapper collects those pubkeys, adds relay hints, and computes each recipient's share from the total weight. If all weights are zero, it normalizes the set to equal weights. That turns one event into a payment group.

This matters because most zap buttons are designed around one recipient. A profile zap pays a profile. A note zap usually pays the author. A split zap lets a post or product encode a recipient set: contributors, creators, list members, collaborators, or people included by another tool. Zapper is useful precisely because it will follow that payment shape instead of forcing every payment back to one author.

The code creates a separate zap object for each recipient. It divides the sender's chosen sat amount by recipient weight, converts it to millisats, attaches profile metadata where available, and then sends recipients one by one. The UI can retry unsent zaps. That is important because a bulk payment is rarely atomic. One recipient can fail because of metadata, LNURL, wallet or invoice issues while another succeeds.

The risk is equally direct: a split payment should be inspected as a recipient list, not treated as a single tap. If a note includes hundreds of recipients, if a weight looks strange, or if the UI hides who is being paid, you should not continue. Split zaps are powerful because they turn social context into payment routing. That same power makes wrong context expensive.

Zap, anonymous zap and send sats

Zapper exposes three payment types in code: `zap`, `anon-zap` and `send-sats`. The difference is not cosmetic. A normal zap is meant to be published on Nostr under your name. An anonymous zap is still a zap-style request, but the app signs it with a generated private key instead of your Nostr account. A send-sats payment skips the Nostr event and sends a Lightning payment without a public zap request.

Normal zaps use NIP-57's kind 9734 zap request pattern. Zapper builds an event with `relays`, `amount` and `p` tags, adds `a` or `e` target tags when an event target exists, and asks `window.nostr.signEvent` to sign it. The live HTML loads `nostr-login` with `data-perms="sign_event:9734"`, which matches that focused permission.

Anonymous zaps are a useful halfway house, but they should not be misunderstood. The app generates a one-time private key, signs the zap request and fetches an invoice. That keeps the zap from being signed by your normal Nostr key, but the payment still touches a wallet, an invoice endpoint and potentially wallet-side metadata. Anonymous in the zap event is not the same as privacy against every observer.

`send-sats` changes the flow again. In the invoice fetcher, Zapper only appends the encoded Nostr zap event to the LNURL callback when the type is not `send-sats`. That means a plain send-sats payment can be useful when you want to pay a Lightning address discovered through Nostr metadata without creating a public zap event. The tradeoff is that Nostr clients may not display it as a zap.

Wallet and signer surfaces

Zapper depends on two different browser surfaces. The first is `window.nostr`, usually supplied by a NIP-07-compatible signer or login layer. Zapper checks for that interface and uses it only when a normal named zap needs to be signed. If you are not logged in or do not have a signer, a normal zap can fail with an instruction to use a browser extension to log in.

The second surface is WebLN. The app watches for `window.webln`, enables it when found, and then uses `window.webln.sendPayment(invoice)` when payment is available. It also initializes the Bitcoin Connect React button with the app name Zapper. In practice, this means the payment path can be a browser wallet, Bitcoin Connect provider or manual Lightning invoice, depending on what the sender has installed and authorized.

Those surfaces should be verified separately. Signing a zap request is not the same as paying the invoice. A Nostr signer proves which public key authored the zap request. A wallet pays sats. If a page asks for both, the user should understand which prompt belongs to identity and which prompt belongs to money. Zapper's narrow permission for kind 9734 helps, but the wallet prompt is still the part that moves funds.

The QR fallback is not second-class. When no WebLN provider is available, the modal displays the invoice, a QR code, a copy button and a wallet link. This keeps Zapper usable from a regular browser and gives the sender time to inspect the invoice. For larger or unfamiliar split zaps, manual payment can be safer than an auto-connected wallet because it gives you one more pause.

Where NWC fits

Zapper appears in the broader Nostr Wallet Connect ecosystem discussion. The NWC ecosystem post from May 9, 2025 described Zapper as a micro-app for bulk Lightning payments to multiple recipients and said it was now with NWC. The live code also uses Bitcoin Connect, which is the Alby-backed connection layer many users recognize from NWC-enabled wallet flows. That makes Zapper relevant to the NWC map.

The clean boundary is this: Zapper is not itself a wallet service. It does not hold your sats. It prepares zap/payment requests and asks a wallet-facing provider to pay. NWC, when present through a connected wallet or Bitcoin Connect flow, belongs on the wallet authorization side of the transaction. Zapper is the application asking for payment, not the account that stores funds.

That difference matters for risk. If your wallet connection has broad `pay_invoice` authority, a small app can become a large spend surface. If the wallet connection is scoped with a budget, expiration and revocation path, the same app becomes much less scary. Zapper's own UI still needs target and recipient clarity, but the wallet-side controls decide how much damage a mistaken click can do.

A responsible Zapper setup uses small budgets and narrow permissions. Test a one-sat or ten-sat flow first. Confirm that the wallet prompt shows the expected invoice and amount. Revoke or rotate NWC-style connections when you are done testing. Nostr payments feel smooth when the connection is right, but smoothness should not remove the human check.

Developer integration path

Zapper is useful to other builders because integration does not require a large SDK. The README says an app can redirect to the `/zap` endpoint and include query parameters. The `id` parameter is required. `amount`, `comment`, `type` and `auto_send` are optional. That is a modest contract, and modest contracts are often how small Nostr tools spread across clients.

An app that wants to support zaps can therefore offload a lot of edge cases. It does not need to implement LNURL discovery, split-weight handling, NIP-57 zap request construction, WebLN fallback, QR rendering and retry UI all at once. It can hand the user to Zapper. That is especially attractive for experimental clients, publishing tools or community apps whose main job is not payment UX.

The `auto_send` parameter deserves special care. Zapper removes it from the URL after noticing it, recalculates zaps, then starts a short timer before triggering the hidden send action. That is convenient for guided flows, but it is dangerous if paired with a wallet connection that can pay without careful user review. Developers should use `auto_send` only where the user has already reviewed the exact action.

The safest integration pattern is to generate a visible link first. Show the target, amount, comment and payment type inside your own app. Then open Zapper for final payment. If you embed it in an iframe, make the boundaries obvious. A user should never wonder whether they are authorizing your app, Zapper, the signer or the wallet.

Relays, metadata and invoices

Zapper's payment flow relies on several discovery steps. It needs relays to fetch the target event and recipient metadata. It needs kind 0 profile metadata to read `lud16` or `lud06`. It needs LNURL-pay to return a callback. It needs that callback to report whether Nostr zaps are supported, through `allowsNostr` and `nostrPubkey`, when the user is doing a zap rather than a plain send-sats payment.

This layered flow explains many possible failures. The event may not be reachable on the relays Zapper tries. A profile may lack a Lightning address. A Lightning address may return a broken LNURL response. A recipient may allow Lightning tips but not Nostr zaps. A signer may reject the event. A wallet may reject the invoice. Zapper can catch errors, but it cannot remove the underlying dependencies.

The relay default is also worth noticing. The loader starts with `wss://relay.nostr.band/`, while the NDK setup adds `wss://relay.nostr.band/all`. Relay hints from NIP-19 identifiers and zap tags can expand that set. This is pragmatic, but it means target visibility depends on where the event and metadata can be found. If a note is missing, try opening the target in another client before assuming Zapper is broken.

Invoices come from recipient LNURL endpoints, not from Zapper inventing money routes. The fetcher appends the amount, and for zaps it appends the encoded Nostr zap request as the `nostr` parameter. It then expects a Lightning invoice in the `pr` field. That is exactly where sender caution belongs: invoice generation is external to Zapper, so inspect the displayed invoice and recipient before paying.

Receipts and display limits

NIP-57 does not stop at the zap request. A complete visible zap usually depends on a zap receipt, kind 9735, published by or on behalf of the recipient's LNURL service. Zapper's job in the sender flow is to construct the request, fetch the invoice and pay or display it. Whether a receipt appears in every Nostr client depends on the recipient service, relays, client support and receipt validation.

That is why a paid invoice and a visible zap are related but not identical user experiences. Your wallet may show that the invoice was paid. A client may or may not show a public zap receipt near the original event. A split payment may produce some visible receipts and some failures. Zapper can tell you what it attempted and what the wallet returned, but it is not the final display authority for the whole network.

For normal zaps, the signer identity also matters. If you expected your public key to appear as the zapper, confirm that you were logged in with the right signer before paying. If you selected anonymous zap, do not expect your normal profile to get social credit. If you selected send-sats, do not expect Nostr clients to show a zap at all. The payment type should match the social outcome you want.

This is the quiet reason tools like Zapper are valuable. They force the payment type into a visible choice. Many users say zap when they mean three different things: a public Nostr zap, an anonymous zap-style payment, or a private Lightning tip. Zapper makes those differences explicit enough that a careful user can choose rather than guess.

Maintenance and operator trail

The public GitHub repository is `nostrband/zapper`, with the description Zapper nostr micro app and homepage `https://zapper.nostrapps.org`. The repository metadata checked during this review showed the default branch as `main`, a last push on September 20, 2024, and the GitHub page itself still reachable in June 2026. The live production bundle exposed a Vercel commit hash from the same repository family.

That maintenance profile is not a reason to dismiss Zapper, but it is a reason to test the live app rather than relying only on old screenshots. Payment apps age in two directions. The Nostr protocol pieces can remain stable, while wallet connectors, browser extension behavior, LNURL services and dependency versions can change around them. A working 2024 build can still be useful, but users should verify it against their current wallet.

The package file names React, Material UI, NDK, nostr-tools, qrcode, Bitcoin Connect React and other ordinary web dependencies. This is a client-side app, not a heavy server product. That means much of the trust question is visible in the browser bundle and source repository. It also means the app depends on external services for relays, profile metadata and recipient invoice generation.

The operator trail points to the Nostr.Band ecosystem. The mirror domain is under `nostrapps.org`, the code organization is `nostrband`, and the relays default to Nostr.Band endpoints. That context helps explain why Zapper is built as a micro-app: it is one utility in a larger Nostr tooling neighborhood, not a standalone financial institution.

Practical checks before use

Start by checking the target. If a link opens Zapper with an `id` parameter, compare that target in a normal Nostr client. Is it the profile, note, event or addressable object you expected? If the target is a split-zap event, inspect the recipients. Do not pay a split just because the source page looked trustworthy. The actual recipient list is the payment instruction.

Next, check the payment type. Use a normal zap only when you want the zap request associated with your Nostr key. Use anonymous zap when you do not want your normal key attached, while remembering that wallet metadata may still exist elsewhere. Use send-sats when you want a Lightning tip without the public Nostr zap layer. The wrong type can create the wrong public record.

Then check the wallet path. If Bitcoin Connect or WebLN asks for permission, confirm the wallet, amount and budget. If you use an NWC-style wallet connection, keep it scoped and revocable. If Zapper shows a QR code or invoice text, compare the amount and recipient context before paying. A manual QR scan is not automatically safer if you scan the wrong invoice without reading it.

Finally, test small. Split zaps, auto-send links and new wallet connectors should begin with tiny amounts. Retry behavior is useful, but retries can also make a failed multi-recipient flow confusing if you are not watching which recipients already succeeded. Treat the first run as a payment drill, not a performance.

The bottom line

Zapper earns its place because it does one Nostr payment job well enough to study: take a Nostr target, understand whether it points to a profile, event or addressable object, honor split-zap tags when present, and help the sender pay through a connected or manual Lightning flow. It is not a broad product, and that is part of its usefulness.

Its best use case is the moment when a normal client cannot or should not own all zap logic. A publishing app can redirect to Zapper. A split-zap experiment can point users at Zapper. A user can tip an event from a browser that does not have the right native zap button. The app becomes connective tissue between Nostr objects and Lightning wallets.

The caution is that connective tissue can still move real money. Target lookup, relay reachability, LNURL metadata, signer prompts, wallet permissions and invoice payment are all separate failure points. Zapper makes those pieces easier to use, but it does not make them disappear. The reader's job is to verify the object, recipients, type, amount and wallet connection before sending.

If you want a full wallet, use a wallet. If you want a social client, use a social client. If you want a compact zap handoff that can handle split recipients and lets other apps avoid rebuilding the same payment flow, Zapper is worth opening. Just keep the first payments small, keep wallet permissions narrow, and read the screen before the sats leave.

Sources worth opening

Open the live app, the `/zap` route, the GitHub README, source files for target loading, zap construction, WebLN payment and QR fallback, then compare NIP-57, NIP-07, NIP-19, LNURL and the NWC ecosystem references. That combination shows what Zapper actually does and where the trust boundary sits.

Back to the Crays Nostr page
Apps route visual cue 1
Apps route visual cue 2
Apps route visual cue 3
Apps route visual cue 4
Apps route visual cue 5

How to use this page

Keep the product map close.

Search the wider app shelf when you want another client, tool, protocol reference or source trail beside this page.

AppsThe Apps route stays openApps pages stay availableProducts, tools, communities and source trails.Browse pages
Apps contribution visual cue 1
Apps contribution visual cue 2
Apps contribution visual cue 3
Apps contribution visual cue 4
Apps contribution visual cue 5

Bring something back

Ask, suggest, submit or nominate.

Ask a question, send a source, suggest a fix, submit a project or nominate a public Nostr account. The page stays stable; your contribution gets reviewed beside it.