nostr-tools
The essential JavaScript library for Nostr development. Create keys, sign events, connect to relays.
Overview
nostr-tools is the go-to library for building Nostr applications in JavaScript/TypeScript. It provides everything from key generation to relay management to NIP implementations.
Installation
# npm
npm install nostr-tools
# JSR (Deno/modern runtimes)
npx jsr add @nostr/tools
Requires TypeScript >= 5.0 if using TypeScript.
Core Features
Key Generation
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure';
// Generate new keypair
const sk = generateSecretKey(); // Uint8Array
const pk = getPublicKey(sk); // hex string (npub derivable)
console.log('Public key:', pk);
// Keep sk secret!
Creating Events
import { finalizeEvent, verifyEvent } from 'nostr-tools/pure';
const event = finalizeEvent({
kind: 1, // Text note
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: 'Hello, Nostr!'
}, sk);
// Event now has id and sig
console.log('Event ID:', event.id);
// Verify the event
const isValid = verifyEvent(event);
Connecting to Relays
import { Relay } from 'nostr-tools/relay';
// Connect to a relay
const relay = await Relay.connect('wss://relay.damus.io');
console.log('Connected to', relay.url);
// Subscribe to events
const sub = relay.subscribe([
{ kinds: [1], limit: 10 }
], {
onevent(event) {
console.log('Received:', event.content);
},
oneose() {
console.log('End of stored events');
}
});
// Publish an event
await relay.publish(event);
// Close subscription when done
sub.close();
Relay Pool
Manage multiple relays:
import { SimplePool } from 'nostr-tools/pool';
const pool = new SimplePool();
// Publish to multiple relays
await Promise.all(
pool.publish(['wss://relay1.example', 'wss://relay2.example'], event)
);
// Query across relays
const events = await pool.querySync(
['wss://relay1.example', 'wss://relay2.example'],
{ kinds: [1], authors: [pk], limit: 20 }
);
// Subscribe across relays
const sub = pool.subscribeMany(
['wss://relay1.example', 'wss://relay2.example'],
[{ kinds: [1], limit: 10 }],
{
onevent(event) {
console.log(event);
}
}
);
NIP Implementations
NIP-19: Bech32 Encoding
import { nip19 } from 'nostr-tools';
// Encode
const npub = nip19.npubEncode(pk); // npub1...
const nsec = nip19.nsecEncode(sk); // nsec1...
const note = nip19.noteEncode(eventId); // note1...
// Decode
const { type, data } = nip19.decode(npub);
// type: 'npub', data: hex pubkey
NIP-04: Encrypted DMs
import { nip04 } from 'nostr-tools';
// Encrypt
const ciphertext = await nip04.encrypt(sk, recipientPk, 'Secret message');
// Decrypt
const plaintext = await nip04.decrypt(sk, senderPk, ciphertext);
NIP-44: Newer Encryption
import { nip44 } from 'nostr-tools';
// Encrypt with NIP-44 (recommended for new apps)
const ciphertext = nip44.encrypt(sk, recipientPk, 'Secret message');
// Decrypt
const plaintext = nip44.decrypt(sk, senderPk, ciphertext);
NIP-98: HTTP Auth
import { finalizeEvent } from 'nostr-tools';
// Create auth event
const authEvent = finalizeEvent({
kind: 27235,
created_at: Math.floor(Date.now() / 1000),
tags: [
['u', 'https://api.example.com/resource'],
['method', 'GET']
],
content: ''
}, sk);
// Use in Authorization header
const response = await fetch('https://api.example.com/resource', {
headers: {
'Authorization': `Nostr ${btoa(JSON.stringify(authEvent))}`
}
});
Advanced Features
WebAssembly Support
For better performance in browsers:
import { setNostrWasm, generateSecretKey, finalizeEvent } from 'nostr-tools/wasm';
import { initNostrWasm } from 'nostr-wasm';
// Initialize WASM
const wasm = await initNostrWasm();
setNostrWasm(wasm);
// Now operations use WASM
const sk = generateSecretKey();
Custom WebSocket Implementation
import { useWebSocketImplementation } from 'nostr-tools/pool';
import WebSocket from 'ws'; // Node.js
useWebSocketImplementation(WebSocket);
Relay Ping/Reconnect
const pool = new SimplePool({
enablePing: true, // Heartbeat to detect disconnects
enableReconnect: true // Auto-reconnect with exponential backoff
});
NIP-46: Remote Signing (Bunker)
import { BunkerSigner } from 'nostr-tools/nip46';
// Connect to a remote signer
const signer = new BunkerSigner(
clientSecretKey,
'bunker://pubkey?relay=wss://relay.example'
);
await signer.connect();
// Sign events remotely
const event = await signer.signEvent({
kind: 1,
content: 'Signed by bunker',
tags: [],
created_at: Math.floor(Date.now() / 1000)
});
Higher-Level Libraries
For more abstraction, see @nostr/gadgets which builds on nostr-tools.
Links
- npm: nostr-tools
- JSR: @nostr/tools
- GitHub: nbd-wtf/nostr-tools
See Also
- Nostr Protocol — Protocol documentation
- Nostr Getting Started — Tutorial
- Noskey — CLI key generation
- Authentication — NIP-98 auth