basic-nostr
An intentionally tiny NOSTR library for Python: Keys, DMs, Posts, & Products.
Description
basic-nostr does exactly four things:
- Generate Nostr keys
- Send and read direct messages (in both formats NIP-04 and NIP-17)
- Post and read NIP-01 notes (kind 1)
- Post and read NIP-99 products (kind 30402)
I made basic-nostr because no other Python packages make it this simple.
If it does exactly what you need → great, use it. If it doesn't → don't use it. Simple as that.
Install
pip install basic-nostr
Usage
All functions take keys as bech32 nsec1.../npub1... strings (you never need to think about hex).
NostrClient (recommended)
NostrClient handles relay connections and async internals for you. No asyncio knowledge needed. Connects automatically on first use.
from basic_nostr import make_keys, NostrClient
npub, nsec = make_keys()
print(npub) # npub1... (share this)
print(nsec) # nsec1... (keep secret — paste into Amethyst to log in)
nostr = NostrClient(nsec)
# Post a note
nostr.make_post("Hello Nostr!", tags=[["t", "introduction"]])
# Read posts — filter by author, hashtag, or both
posts = nostr.read_posts(authors=[npub], limit=20)
posts = nostr.read_posts(tag_filters={"t": ["monero"]})
# Send DM (NIP-17 by default — sender hidden from relays)
nostr.send_dm(their_npub, "hey!")
nostr.send_dm(their_npub, "hey!", protocol="nip04") # legacy (older clients)
nostr.send_dm(their_npub, "hey!", protocol="both") # maximum compatibility
# Read DMs (reads both NIP-17 and NIP-04 by default)
dms = nostr.read_dms()
for dm in dms:
print(f"From: {dm['sender']}") # npub1...
print(f"Message: {dm['message']}")
print(f"Protocol: NIP-{dm['nip']}") # 17 or 4
print(f"Time: {dm['timestamp']}") # unix timestamp
# List a product — shows up on Shopstr, Plebeian Market, etc.
nostr.list_product(
title="Vintage Keyboard",
description="Cherry MX Blues, great condition.",
price=75,
currency="USD",
image_urls=["https://example.com/keyboard.jpg"],
categories=["electronics"],
condition="used",
location="US",
)
# Read products and parse tags
products = nostr.read_products(limit=50)
for product in products:
tags = {t[0]: t[1:] for t in product["tags"]}
print(f"{tags['title'][0]} — {tags['price'][0]} {tags['price'][1]}")
# Close when done (or use context manager below)
nostr.close()
Read-only usage (no private key needed):
nostr = NostrClient()
posts = nostr.read_posts(tag_filters={"t": ["monero"]})
products = nostr.read_products(limit=10)
nostr.close()
Context manager works too (auto-closes):
with NostrClient(nsec) as nostr:
nostr.make_post("Hello!")
Custom relays:
nostr = NostrClient(nsec, relay_urls=["wss://relay.damus.io", "wss://nos.lol"])
nostr.make_post("Hello from custom relays!")
Async API
All async functions are also exported if you need them directly:
import asyncio
from basic_nostr import make_keys, connect_to_relays, close_relays, make_post, read_posts
async def main():
npub, nsec = make_keys()
relays = await connect_to_relays()
try:
await make_post(relays, "Hello Nostr!", [["t", "introduction"]], nsec)
posts = await read_posts(relays, authors=[npub], limit=20)
finally:
await close_relays(relays)
asyncio.run(main())
Available async functions: connect_to_relays, close_relays, make_post, read_posts, list_product, read_products, send_dm, read_dms, read_events_from_relays.
Contributing
If you want to add more functionality to this, open a PR. I'll merge it if it keeps it simple and matches the patterns.
Metadata
Release files for basic-nostr 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| basic_nostr-1.1.0.tar.gz | 16.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| basic_nostr-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.6 kB
Release files / basic_nostr-1.1.0.tar.gz
| Download URL | basic_nostr-1.1.0.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
55d15b549dbce2297e6cfad3d550876d6437fa89dea766c20e0acab1c1d181ca
|
|
BLAKE2b-256 checksum How to use checksums |
038a4808f8a598d78cf3d18f39e3cd1f3dda62c018340d6202e3b982719e4ab4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Release files / basic_nostr-1.1.0-py3-none-any.whl
| Download URL | basic_nostr-1.1.0-py3-none-any.whl |
|---|---|
| Size | 17.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
237905f568138d29a0d917010fa32a01f42cbb16334b7405c50d782b3d724109
|
|
BLAKE2b-256 checksum How to use checksums |
47009eddce3243d7f0fa8598a47133a056bcf0b2a7fbdd8b7f379788abff37a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|