Skip to content

Instantly share code, notes, and snippets.

@lontivero
Created April 22, 2025 18:26
Show Gist options
  • Save lontivero/2109d729981b8e1bf966364ac948d484 to your computer and use it in GitHub Desktop.
Save lontivero/2109d729981b8e1bf966364ac948d484 to your computer and use it in GitHub Desktop.
Dump Nostr Notes for a given PubKey

Nostr Notes Fetcher

A bash script for fetching all notes from a specific Nostr public key and saving them as individual JSON files.

Overview

This script connects to a Nostr relay via WebSocket, subscribes to receive all notes from a specified public key, and saves each note as a separate JSON file. It's useful for archiving, analyzing, or backing up Nostr content.

Requirements

  • Bash shell environment
  • websocat - WebSocket client tool
  • jq - JSON processor

Installation

  1. Download the script file
  2. Make the script executable:
    chmod +x fetch_nostr_notes.sh
    

Usage

Basic usage:

./fetch_nostr_notes.sh <relay_websocket_url> <pubkey> [output_directory]

Parameters

   * relay_websocket_url: WebSocket URL of the Nostr relay (e.g., wss://relay.damus.io)
   * pubkey: The Nostr public key in hex format to fetch notes from
   * output_directory: (Optional) Directory to save notes to (default: "nostr_notes")

Example

./fetch_nostr_notes.sh wss://relay.primal.net 9e30e940238cd9ebebc6328176dd4d109812129442f2a6c38727fc66fa7ea90a my_notes

This will:

Connect to the relay at wss://relay.primal.net
Request all notes from @lontivero's public key 9e30e940238cd9ebebc6328176dd4d109812129442f2a6c38727fc66fa7ea90a
Save them as individual JSON files in the "my_notes" directory

Output

The script creates a directory (default: "nostr_notes" if not specified) and saves each note as a separate JSON file.

Each file:

Is named with the note's ID (e.g., a1b2c3d4e5f6.json)
Contains the complete JSON data of the note
Includes all metadata such as timestamp, tags, and signatures

The script also provides a running output showing:

When notes are saved
Timestamps of notes
Brief previews of note content

Error Handling

The script will exit with an error if the required parameters are not provided
Timestamps are converted to human-readable dates when possible
The script reports end-of-stored-events when the relay completes sending all available notes

Customization

You can modify the script to change:

The subscription parameters (e.g., add a time range by changing the REQ parameters)
The output format by modifying the jq commands
The maximum number of notes by adjusting the "limit" parameter in the subscription request

License

This script is provided under the MIT License. Contributing

Feel free to submit issues or pull requests with improvements or bug fixes.

#! /usr/bin/env nix-shell
#! nix-shell -i bash -p websocat jq
# Usage: ./fetch_nostr_notes.sh wss://relay.primal.net 9e30e940238cd9ebebc6328176dd4d109812129442f2a6c38727fc66fa7ea90a my_notes
set -e
RELAY_URL=$1
PUBKEY=$2
OUTPUT_DIR=${3:-"nostr_notes"}
if [[ -z "$RELAY_URL" || -z "$PUBKEY" ]]; then
echo "Usage: $0 <relay_websocket_url> <pubkey> [output_dir]"
echo "Example: $0 wss://relay.damus.io 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d nostr_notes"
exit 1
fi
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Generate a random subscription ID
SUBSCRIPTION_ID="dump-my-notes-subscription-id"
# Connect to the Nostr relay and request notes
{
# Send the subscription request for the specified pubkey
echo '["REQ", "'$SUBSCRIPTION_ID'", {"authors": ["'$PUBKEY'"]}]'
# Keep the connection open to receive notes
while true; do
sleep 1
done
} | websocat "$RELAY_URL" | while read -r line; do
# Check if the message is a note (EVENT)
if echo "$line" | grep -q '"EVENT"'; then
# Extract event data
EVENT_DATA=$(echo "$line" | jq -r '.[2]')
EVENT_ID=$(echo "$EVENT_DATA" | jq -r '.id')
# Save the event to a file
echo "$EVENT_DATA" | jq '.' > "$OUTPUT_DIR/$EVENT_ID.json"
echo "Saved note with ID: $EVENT_ID"
# Print basic info about the note
CREATED_AT=$(echo "$EVENT_DATA" | jq -r '.created_at')
CONTENT=$(echo "$EVENT_DATA" | jq -r '.content' | cut -c 1-50)
DATE=$(date -d @"$CREATED_AT" 2>/dev/null || date -r "$CREATED_AT" 2>/dev/null || echo "Timestamp: $CREATED_AT")
echo " Date: $DATE"
echo " Content: $CONTENT..."
echo ""
elif echo "$line" | grep -q '"EOSE"'; then
# End of stored events
echo "Finished receiving all stored events."
exit 0
fi
done
echo "Script completed"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment