An intentionally tiny Nostr library for Python: Keys, DMs, Posts, & Products.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file basic_nostr-1.1.0.tar.gz.
File metadata
- Download URL: basic_nostr-1.1.0.tar.gz
- Upload date:
- Size: 16.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55d15b549dbce2297e6cfad3d550876d6437fa89dea766c20e0acab1c1d181ca
|
|
| MD5 |
da1897213d14f7eb385c972f6538ce3c
|
|
| BLAKE2b-256 |
038a4808f8a598d78cf3d18f39e3cd1f3dda62c018340d6202e3b982719e4ab4
|
File details
Details for the file basic_nostr-1.1.0-py3-none-any.whl.
File metadata
- Download URL: basic_nostr-1.1.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
237905f568138d29a0d917010fa32a01f42cbb16334b7405c50d782b3d724109
|
|
| MD5 |
774ed7753b87cf35972324df371a7fd3
|
|
| BLAKE2b-256 |
47009eddce3243d7f0fa8598a47133a056bcf0b2a7fbdd8b7f379788abff37a3
|