draft optional
Two ephemeral event kinds for privacy-preserving geospatial presence and location sharing on Nostr. Publishers broadcast coarse-grained presence beacons for public discovery, then share precise coordinates only with specific recipients via NIP-44 encryption after consent is established. The same primitives support both real-time mobile tracking and static venue privacy for addressable events.
Standalone. This NIP works independently on any Nostr application.
Location-aware applications on Nostr — delivery, field services, event coordination, fleet tracking, calendar events, marketplace listings — need a standard way to publish presence and share precise coordinates without leaking location data to the network at large. Existing approaches either expose exact coordinates publicly or require centralized location servers.
This NIP defines a two-tier model: coarse public discovery via geohash-indexed beacons, and precise private sharing via NIP-44 encrypted updates. The progressive reveal pattern ensures that location precision never increases without the publisher's consent.
- NIP-38 (User Statuses): User statuses carry text like "working" or "at the gym" with no geospatial semantics, no geohash indexing, no encryption model, and no progressive precision reveal. Presence beacons require geohash
gtags for relay-side spatial filtering, which NIP-38 does not define. - NIP-52 (Calendar Events): Calendar events represent confirmed, scheduled happenings with static locations. Presence beacons represent real-time, ephemeral location signals from mobile publishers. The use cases do not overlap.
- "Why not
gtags on any event kind?": A dedicated presence kind (20500) enables relay-side subscriptions by geohash without downloading all events of every kind in an area. Clients subscribing to{kinds:[20500], #g:["gcpu"]}receive only presence signals; without a dedicated kind, they would receive every geotagged note, calendar event, and marketplace listing in the cell.
| kind | description |
|---|---|
| 20500 | Presence Beacon — coarse geospatial presence (ephemeral) |
| 20501 | Location Update — precise coordinates, encrypted (ephemeral) |
All latitude/longitude values in this NIP use the WGS 84 (EPSG:4326) coordinate reference system — the standard used by GPS receivers and most mapping services. Geohash encoding (used in g tags) is defined over WGS 84 coordinates.
| Precision | Approximate Cell Size | Recommended Use |
|---|---|---|
| 3 | ~156 km x 156 km | Regional fallback, rural areas |
| 4 | ~39 km x 39 km | City-level presence, default for beacons |
| 5 | ~5 km x 5 km | Neighbourhood-level, service areas |
| 6 | ~1.2 km x 1.2 km | Post-consent only (NIP-44 encrypted) |
| 7+ | <300 m | Active sharing only (NIP-44 encrypted, never public) |
To avoid edge effects when a publisher is near a geohash cell boundary, subscribers MUST subscribe to the target cell plus its eight neighbours:
+-------+-------+-------+
| NW | N | NE |
+-------+-------+-------+
| W | * | E |
+-------+-------+-------+
| SW | S | SE |
+-------+-------+-------+
* = subscriber's cell
This ensures that a publisher positioned at a cell edge is visible to subscribers on either side of the boundary.
Location precision increases as trust increases:
- Public discovery: Geohash precision 4-5 only (~5-40 km). Anyone can see approximate area.
- Post-consent: Geohash precision 6+ (~1.2 km). Encrypted to specific recipients.
- Active sharing: Exact coordinates via
kind:20501. NIP-44 encrypted to named recipients.
The following diagram illustrates the progressive reveal flow from public discovery through consent to active sharing:
sequenceDiagram
autonumber
participant S as Subscriber
participant R as Relay
participant P as Publisher
rect rgb(27, 45, 61)
Note over S,P: Phase 1 — Public Discovery (precision 4-5, ~5-40 km)
P->>R: kind:20500 Presence Beacon<br/>g=gcpu, status=available
P->>R: kind:20500 Beacon (30s interval)
S->>R: REQ {kinds:[20500], #g:[9-cell neighbours]}
R-->>S: Matching beacons
Note over S: Sees approximate area only
end
rect rgb(45, 45, 27)
Note over S,P: Phase 2 — Consent Established (application-specific)
S->>P: Consent exchange (out of band)
P-->>S: Consent acknowledged
end
rect rgb(27, 61, 45)
Note over S,P: Phase 3 — Active Sharing (exact coordinates, NIP-44 encrypted)
P->>R: kind:20501 Location Update<br/>NIP-44 encrypted to Subscriber<br/>consent=explicit
R-->>S: Encrypted location update
Note over S: Decrypts: lat, lon,<br/>accuracy, bearing, speed
P->>R: kind:20501 (every few seconds)
R-->>S: Encrypted location update
end
rect rgb(61, 27, 27)
Note over S,P: Termination — context ends
Note over P: Stops publishing
Note over R: Ephemeral events expire<br/>via NIP-40 expiration tags
end
Ephemeral event declaring presence in a geographic area. Publishers SHOULD publish every 30 seconds whilst active, with a 30-minute NIP-40 expiration tag as a safety net.
{
"kind": 20500,
"pubkey": "<publisher-hex-pubkey>",
"created_at": 1698765432,
"tags": [
["g", "gcpuu"],
["g", "gcpu"],
["status", "available"],
["alt", "Presence beacon: available in gcpuu"],
["expiration", "1698767232"]
],
"content": "",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}g(REQUIRED, one or more): Geohash at precision 4-5. Multiple tags MAY be used to publish at multiple precision levels simultaneously.status(REQUIRED): One ofavailable,busy,offline.expiration(REQUIRED): NIP-40 expiration timestamp. MUST be set (30-minute maximum recommended). Safety net — if the publisher stops broadcasting, stale beacons expire automatically.
Optional tags that publishers MAY include for richer discovery:
t: Freeform category tag (e.g.plumber,courier,photographer). Enables category-filtered discovery.
Clients subscribing to presence beacons use a REQ filter like:
{
"kinds": [20500],
"#g": ["gcpuuz", "gcpuuy", "gcpuux", "gcpuuv", "gcpuuw", "gcpvn0", "gcpvn1", "gcpvn2", "gcpvn3"]
}The nine geohash values correspond to the subscriber's cell and its eight neighbours.
Ephemeral event sharing precise coordinates with specific recipients. ALL location data is NIP-44 encrypted — relays can see that a location update exists but MUST NOT be able to read the coordinates.
{
"kind": 20501,
"pubkey": "<publisher-hex-pubkey>",
"created_at": 1698765432,
"tags": [
["p", "<recipient-pubkey>"],
["g", "gcpuu"],
["context", "<shared-context-id>"],
["consent", "explicit"],
["alt", "Encrypted location update for shared context"],
["expiration", "1698765462"]
],
"content": "<NIP-44 encrypted JSON>",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}p(REQUIRED, one or more): Pubkeys of recipients. The content is NIP-44 encrypted pairwise to the recipient. When multipleptags are present, the publisher MUST fan out separate events — one per recipient — each with content encrypted pairwise to that recipient's pubkey.g(RECOMMENDED): Coarse geohash (precision 4-5) derived from the encrypted coordinates. Enables relay-side geographic filtering without revealing exact location. When GPS is unavailable, this tag MAY be omitted if alocation_status: gps_losttag is present instead.context(RECOMMENDED): An identifier scoping this location stream to a shared context (e.g. a task, order, event, or session). Enables filtering.consent(REQUIRED): Declares the basis for location sharing. MUST be one of:explicit— Publisher has explicitly consented to share location.contextual— Location sharing is a condition of the shared context.policy— Location sharing is required by a platform or service policy.
expiration(RECOMMENDED): NIP-40 expiration timestamp.
The content field is a JSON object NIP-44 encrypted pairwise to the recipient (one event per recipient when multiple p tags are used):
| Field | Type | Required | Description |
|---|---|---|---|
lat |
Decimal degrees | Yes | Latitude |
lon |
Decimal degrees | Yes | Longitude |
accuracy_meters |
Meters | Yes | GPS accuracy radius |
bearing |
Degrees (0-360) | No | Direction of travel (0 = north, 90 = east) |
speed_kmh |
Km/h | No | Current speed |
altitude_meters |
Meters | No | Altitude above sea level |
timestamp |
Unix timestamp | Yes | Time of the GPS fix |
Example decrypted content:
{
"lat": 51.4950,
"lon": -0.1100,
"accuracy_meters": 8,
"bearing": 355,
"speed_kmh": 32,
"altitude_meters": 45,
"timestamp": 1698765432
}- Discovery phase: Publisher broadcasts
kind:20500beacons at coarse geohash precision (4-5). Subscribers find nearby publishers via nine-cell subscription. - Consent phase: Parties establish a shared context and agree to location sharing (out of band for this NIP — consent mechanisms are application-specific).
- Active sharing phase: Publisher sends
kind:20501updates with NIP-44 encrypted precise coordinates to specific recipients. Updates SHOULD be sent every few seconds during active sharing. - Termination: When the shared context ends, ALL location sharing ceases immediately. Since events are ephemeral, no cleanup is required — stale events expire via
expirationtags.
This NIP defines location event structure and privacy transport rules. It does not prescribe legal/compliance policy or product-specific access policy.
- No auto-reveal requirement: The NIP does not require automatic location disclosure after RSVP, booking, or acceptance.
- Organizer-mediated access supported: Publishers can share
kind:20501only with explicitprecipients approved by organiser or platform policy. - Venue policy is standardised but optional: The
venue-visibilitytag (open,private,semi-private) standardises how applications communicate location privacy policy. Publishers are not required to use it, but when present, clients SHOULD respect it. See Static Location Privacy. - Jurisdictional obligations are app-level: GDPR/PII handling, payment processor scope, and local legal requirements are implementation responsibilities.
The protocol flow above describes real-time location sharing — mobile participants broadcasting presence beacons and streaming coordinates. Many applications also need static location privacy for fixed venues: a home address, a private studio, a community centre that should only be discoverable to approved attendees.
Static location privacy builds on the same two kinds (kind:20500 and kind:20501) but applies them differently.
Addressable events with a physical location (e.g. NIP-52 calendar events, NIP-99 classified listings, marketplace offers) MAY include g tags for relay-side geographic filtering. This is a valid discovery mechanism alongside kind:20500 beacons — the geohash tag enables #g subscription filters without requiring a separate ephemeral beacon.
{
"kind": 31923,
"tags": [
["d", "jazz-night-march"],
["g", "gcpuu"],
["location", "Bristol Community Center"],
["alt", "Calendar event: Jazz Night at Bristol Community Center"]
],
"content": "...",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}The g tag on a non-ephemeral event follows the same precision conventions as beacons: precision 4-5 for public discovery (~5-40 km), never higher than precision 5 on public events.
The venue-visibility tag is OPTIONAL and application-specific. It is not required for the core presence beacon and location update protocol.
Publishers MAY include a venue-visibility tag on any addressable event that has a physical location. This tag declares the location privacy policy for the event:
| Value | Meaning | g tag precision |
Precise location |
|---|---|---|---|
open |
Full address is public | 5 (~5 km) | Published in the event (e.g. geo tag or location tag with full address) |
private |
Approximate area only; precise location granted individually | 4 (~39 km) | NIP-44 self-encrypted in event content; organiser grants per-recipient via kind:20501 |
semi-private |
Approximate area public; precise location auto-granted to group members or confirmed attendees | 5 (~5 km) | NIP-44 self-encrypted in event content; auto-granted on booking confirmation or group membership |
Example:
{
"kind": 31923,
"tags": [
["d", "home-education-meetup"],
["g", "gcpu"],
["venue-visibility", "private"],
["alt", "Private venue event: home education meetup"]
],
"content": "<NIP-44 self-encrypted JSON containing precise location>",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}When venue-visibility is private or semi-private:
- The
gtag SHOULD use a coarser precision (4 for private, 5 for semi-private) to avoid narrowing the area too much. - The precise location (latitude, longitude, full address) SHOULD be NIP-44 encrypted to the publisher's own pubkey and stored in the event
contentfield. - The publisher distributes precise location to approved recipients via
kind:20501location updates (see below).
When venue-visibility is absent, clients SHOULD treat the event as open if a precise location is visible, or infer the policy from available tags.
For static venues, the publisher stores the precise location encrypted to their own pubkey in the addressable event. When a recipient is approved, the publisher decrypts the location locally and re-publishes it as a kind:20501 location update encrypted to the recipient:
- Publisher creates the event with precise location NIP-44 self-encrypted in
content. - Recipient requests access (application-specific — e.g. RSVP, booking request, group membership).
- Publisher approves and publishes
kind:20501:ptag: the approved recipient's pubkey (or multipleptags for bulk grants)contexttag: the addressable event'sa-tag reference (e.g.31923:<pubkey>:<d-tag>)consent:explicitcontent: NIP-44 encrypted JSON withlat,lon,accuracy_meters,timestampexpiration: event end time plus a reasonable buffer (e.g. 2 hours)
- Recipient decrypts and caches the precise location locally.
- Expiry: The ephemeral
kind:20501expires via NIP-40. The recipient's local cache persists (they already know the location), but no new grants are issued.
Applications MAY implement automatic kind:20501 grants based on context:
- Group membership: If the event is linked to a group and the recipient is a verified group member, the publisher's client auto-publishes the grant on RSVP or booking confirmation.
- Booking confirmation: If the event uses a booking system, the publisher's client auto-publishes the grant when the booking is confirmed.
- Coordinator mediation: If a coordinator facilitates the interaction, the coordinator MAY trigger the grant on behalf of the publisher after verifying the recipient.
Auto-grant logic is application-defined. This NIP provides the transport (kind:20501); the trigger policy is above the protocol layer.
The three-tier privacy model maps to specific geohash precisions:
| Tier | Precision | Approximate Area | Use Case |
|---|---|---|---|
| Coarse (public relay) | 4–5 characters | ~20km × 20km to ~5km × 5km | Discovery — "nearby participants" |
| Fine (matched parties) | 7–8 characters | ~150m × 150m to ~40m × 40m | Coordination — "heading to your area" |
| Exact (NIP-44 encrypted) | Full coordinates | Point location | Meetup — "I'm at the front door" |
Recommendations by context:
- Urban areas: Coarse=5, Fine=7 (denser population needs tighter coarse bounds)
- Rural areas: Coarse=4, Fine=6 (wider areas, fewer participants)
- High-security: Coarse=4, Fine=8, Exact only after mutual NIP-44 key exchange
Users share coarse location on a relay to signal "I'm in this neighborhood." Matched friends receive fine location. Exact coordinates shared only when ready to meet.
A distress signal broadcasts coarse location publicly for any nearby responder. Fine location revealed to first responders who acknowledge. Exact coordinates sent encrypted to emergency contacts.
Courier shares fine-tier location updates with the recipient during active delivery. Coarse location visible on a public tracking relay. Exact drop-off coordinates shared at final mile.
Vehicles broadcast coarse location to a fleet relay. Dispatchers receive fine location. Exact coordinates logged for compliance but never broadcast.
- Precision never increases without consent. Public beacons (precision 4-5) reveal only a ~5-40 km area. Exact coordinates are only shared via NIP-44 encrypted
kind:20501events after explicit consent. - Ephemeral events. Both kinds are in the ephemeral range (20000-29999). Relays MUST NOT persist them. This prevents location history accumulation on relays.
- Expiration tags. The
expirationtag ensures stale beacons do not persist if a publisher goes offline without sending anofflinestatus. - Encrypted content.
kind:20501content is NIP-44 encrypted. Relays see that a location update exists but cannot read coordinates. - Consent declaration. The
consenttag makes the basis for location sharing explicit and auditable. - No location history. Ephemeral events are not persisted. Implementations SHOULD NOT build location history from ephemeral events beyond what is needed for the active context.
- Geohash leakage. Even coarse geohashes reveal approximate location. Publishers who require anonymity SHOULD NOT publish
kind:20500beacons at all. - Replay attacks. Consumers SHOULD validate
created_attimestamps and discard events older than a reasonable threshold (e.g. 5 minutes for beacons, 30 seconds for location updates).
{
"kind": 20500,
"pubkey": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"created_at": 1709740800,
"tags": [
["g", "gcpuu"],
["g", "gcpu"],
["status", "available"],
["alt", "Presence beacon: available in gcpuu"],
["expiration", "1709742600"]
],
"content": "",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}{
"kind": 20501,
"pubkey": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"created_at": 1709740800,
"tags": [
["p", "b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3"],
["g", "gcpuu"],
["context", "delivery_order_42"],
["consent", "explicit"],
["alt", "Encrypted location update for delivery order 42"],
["expiration", "1709740830"]
],
"content": "<NIP-44 encrypted JSON>",
"id": "<32-byte-hex>",
"sig": "<64-byte-hex>"
}Decrypted content for the above:
{
"lat": 51.495,
"lon": -0.11,
"accuracy_meters": 8,
"bearing": 355,
"speed_kmh": 32,
"altitude_meters": 45,
"timestamp": 1709740800
}- NIP-01: Basic protocol flow, event format
- NIP-40: Expiration timestamps
- NIP-44: Versioned encrypted payloads
No public reference implementation exists yet. Implementors SHOULD refer to the kind definitions above and the geohash algorithm for computing cell neighbours.
A minimal implementation requires:
- A geohash library capable of encoding coordinates and computing the eight neighbours of a cell.
- A NIP-44 encryption library for encrypting
kind:20501content. - A Nostr client that supports ephemeral event publishing and subscription filtering on
gtags.