Nostr Public Notes Monitor - Verified Relay Watchlists
Pricing
from $1.20 / 1,000 verified public note observations
Nostr Public Notes Monitor - Verified Relay Watchlists
Export signature-verified public Nostr notes from two relays. Filter by author, hashtag or keyword, deduplicate IDs, retain provenance and optionally skip previously saved notes. No key needed.
Pricing
from $1.20 / 1,000 verified public note observations
Rating
0.0
(0)
Developer
Brandt May
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share

Open this Actor in Console · Try a small run · Cost
Mayd-It · Verified public notes
Collect a bounded watchlist of public Nostr notes with signed text and relay provenance. Filter explicit author keys or hashtag tags, deduplicate observations across two relays, and optionally skip notes already saved.
Source scope: Public kind 1 notes from relay.damus.io and nos.lol. Signatures are verified; verification establishes the signing key, not a person’s identity or a post’s truth.
What you get
- Distinct note IDs with original signed content and verified signatures.
- Author, tag, time and literal keyword filters with observed relay provenance.
- Saved-history deduplication for recurring collection without a WebSocket client.
Try a small run
Copy this exact input into the Actor’s JSON input editor, then run it.
{"relays": ["wss://relay.damus.io","wss://nos.lol"],"perRelayLimit": 10,"maxResults": 20,"hashtags": ["nostr"]}
This example requests a ten-event window per relay and saves at most 20 distinct matching notes tagged nostr. No account or API key is required. {} uses the same tag and a seven-day lookback; set your own filters for a watchlist, or explicitly pass "hashtags": [] for an unfiltered recent window. Open the dataset for verified rows and SUMMARY for accepted, rejected and incomplete-source counts.
Understand your run
Open Run report in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use CSV export to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.
The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.
Cost
FREE / BRONZE: $0.002 per saved observation ($2 per 1,000). SILVER: $1.60 per 1,000. GOLD / PLATINUM / DIAMOND: $1.20 per 1,000.
The Actor Start event is $0.00005 per charged start unit, with one unit per GB of Actor memory and a minimum of one. The Pricing tab shows the rate for your Apify tier. New, changed and ordinarily saved unchanged observations use the same result rate. Skipped unchanged rows, rejected events, duplicates and error diagnostics are not paid result rows. Use onlyChanges for repeated monitoring after establishing history.
A real result
Selected fields from a recorded run on 10 October 2026. This is an example of the output shape; source content and counters can change.
{"id": "19befb884f45b68a482cde7cc5a47c4049fba50e0ff97001fa303c9bc6222d60","kind": 1,"createdAt": "2026-10-10T23:14:02.000Z","hashtags": ["bitcoin","moscowtime","nostr"],"sourceRelays": ["wss://nos.lol"],"signatureVerified": true}
This retained sample came from the one-relay community example below. The complete row also includes signed content, its author public key and signature. Relay provenance records where the Actor observed the note.
More examples
Public Nostr Bitcoin Hashtag Notes
Request notes with the exact, case-sensitive bitcoin tag.
{"hashtags": ["bitcoin"],"perRelayLimit": 10,"maxResults": 20}
Nostr Community Tag on nos.lol
Use just nos.lol for the exact nostr tag, with at most ten saved notes.
{"relays": ["wss://nos.lol"],"hashtags": ["nostr"],"perRelayLimit": 10,"maxResults": 10}
This is an experimental market with limited observed Apify demand; no audience-growth or revenue promise is implied. Every event ID is recomputed and its Schnorr signature is checked before a paid row is saved.
Input and coverage
| Input | Behavior |
|---|---|
relays | One or both of wss://relay.damus.io and wss://nos.lol; both by default. Other hosts, credentials, paths and custom ports are rejected. |
authors | Up to 20 exact hexadecimal public keys. No username or npub resolution. Multiple authors use OR. |
hashtags | Up to 10 exact, case-sensitive t tag values, with an optional leading #. Multiple tags use OR. With no author, hashtag or keyword at all, nostr is sampled by default. |
keywords | Up to 10 case-insensitive substrings matched with OR within the retrieved window. This is not full-text search across a relay. |
since, until | Inclusive ISO8601 timestamps with timezone. Omitted end freezes at run start; omitted start is lookbackHours earlier. Maximum span 366 days. |
lookbackHours | Default 168 (seven days), used when since is omitted. |
perRelayLimit | Default 10, maximum 100 stored events per relay. Invalid, duplicate or filtered events can reduce saved results. |
maxResults | Default 20 confirmed saved notes, maximum 1,000. Two supported relays can provide at most 200 candidates per run. |
relayTimeoutSeconds | Default 12 seconds per relay, including DNS and connection; maximum 30. |
comparePrevious, onlyChanges, snapshotName | Optional confirmed-output history described below. |
maxRunSeconds | Default 240 seconds, 30–3,600 allowed, further bounded by the platform timeout minus 25 seconds. |
Author, hashtag, keyword and time groups combine with AND. All filters are checked locally even when sent to a relay. Notes are sorted newest first, then by event ID for ties. Public text can include spam, empty text, links and arbitrary content. Media and linked pages are not fetched, and keyword matching does not infer sentiment or identity.
The Actor waits for EOSE, the relay's acknowledgement that its stored-event response has ended. Missing EOSE, refusals and source errors are recorded as partial or failed coverage. Unsupported, oversized, malformed or unverifiable events are always excluded from output and billing. A completed response with usable verified notes may succeed despite these exclusions, with a warning and categorized rejection counts. If every received event from a source is rejected, that source is marked unusable. Rejected content is never retained; diagnostics contain only the event ID when validly shaped and a reason code.
EOSE completes only the requested bounded response, including processing and rejecting unsupported events. It does not establish all matching history, all public Nostr activity, acceptance of every received event, or the absence of deleted notes. The Actor never publishes events, signs in, authenticates to paid relays, reads private messages, or enriches profiles. Public DNS is checked and pinned for TLS connections; redirects are not followed.
A temporary HTTP 502, 503 or 504 handshake response gets at most one retry after a 500 ms pause, within the original relay time allowance. The attempt outcomes remain in SUMMARY.sourceCoverage. Authentication, access restrictions, redirects, subscription refusals and protocol errors are not retried.
Each message is capped at 128 KiB, each relay response at 4 MiB, and each content field at 64,000 UTF-8 bytes. Up to 500 tags are accepted per event. Oversized or unverifiable notes are not billed. These limits are deliberately smaller than some relay limits and are reported in SUMMARY if encountered.
Results
One dataset row represents one distinct verified note in this run:
| Field | Meaning |
|---|---|
id, pubkey, kind | Signed event ID, author public key and kind 1. |
createdAt, createdAtUnix | Publisher's signed timestamp in UTC and Unix seconds; separate from retrieval time. |
content, tags, hashtags | Original signed text and ordered tags; extracted t tag values. |
signature, signatureVerified | Source signature and successful verification flag. |
sourceRelays | Relays that returned this verified ID during this run. Absence from this list is not proof that another relay lacks it. |
rootEventId, replyToEventId | Unambiguous explicit NIP-10 root/reply markers, otherwise null. Legacy unmarked references are preserved without guessing. |
referencedEventIds, threadReferenceMode | Event references and how they were marked. Referenced posts are not fetched. |
links | At most 100 deduplicated HTTP(S) text links; not visited or safety-certified. |
nostrUri, url | Standard nostr:note... URI and a generated public njump.me viewer link. njump.me is not the fetched data source. |
observedAt, contentHash | Retrieval observation time and SHA256 of the stable signed snapshot. |
comparisonStatus, changedFields, previous, previousObservedAt | Optional comparison evidence; not_requested without history, otherwise new, changed or unchanged. |
SUMMARY includes rowsSaved, rowsObserved (distinct matching candidates considered for output), verifiedMatchingNotes, unchangedSkipped, sourcesSucceeded, sourceCoverage, invalidEvents, rejectionsByReason, filtered, failedSources, windowComplete, limits and status. invalidEvents counts every validation exclusion, including validly signed events exceeding supported size limits; it is not a count of forged signatures. Each source includes reason counts and at most 20 {id, reason} rejection samples. windowComplete describes transport and verification processing, not acceptance of all received events. Source counters are not audience or engagement metrics. A healthy empty query or unchanged repeat warns and succeeds. A zero-output operational failure fails the run. A zero-row spending-limit stop is a normal budget outcome.
Saved history
Set comparePrevious: true or onlyChanges: true, and choose a snapshotName. The first comparison run warns and returns matching notes as new. History is stored in the named nostr-public-notes-monitor-history key-value store and separated by relay, filter and time-window configuration.
Only confirmed saved rows advance their own history. Positive observations from a partial relay response may be saved and remembered, with the run explicitly marked partial; this never establishes completeness or deletions. Unchanged repeats are skipped with onlyChanges. Since signed kind 1 event content is immutable, the same valid ID normally remains unchanged. Relay provenance changes do not create false content changes. No automatic deletions are emitted.
For a repeatable historical comparison, use the same fixed since/until, filters and perRelayLimit, and make maxResults large enough for the whole bounded window. Otherwise later runs may find previously unsaved notes. Relay retention and late-arriving events can also change the observed window.
Use one writer per exact history scope. The Actor checks the stored value again before replacing it and refuses an observed conflicting change; the key-value store offers no atomic compare-and-swap, so this is not a distributed lock. Malformed history is preserved with a diagnostic; use a new snapshotName to begin a fresh scope. At 20,000 remembered IDs, choose a new name or narrower watchlist. Named storage and data retention are under your Apify account's control.
Troubleshooting and support
| If you see… | Check this |
|---|---|
| Fewer notes are saved than requested | Limits bound candidates, not guaranteed matches. Duplicates, filters, unsupported sizes and failed verification can reduce output; inspect categorized rejections in SUMMARY. |
| The relay did not send EOSE | The stored-event response did not complete. Treat coverage as partial even when usable verified notes were saved. |
| A repeat still returns new IDs | Use identical fixed since/until, filters and per-relay limits, with room to save the full bounded window. Late arrivals and relay retention can still change that window. |
For help, open an Actor issue or contact bmay@mayd-it.com. Include the run ID, selected sources and the relevant SUMMARY message. Do not send credentials. This Actor is independent of the platform.
Content remains subject to its creators’ rights and applicable law. Use public data for a legitimate purpose, honor deletion requests and avoid attempting to identify anonymous authors. Storage charges follow your Apify plan.
Protocol references: NIP-01 events and subscriptions, NIP-10 marked reply references, NIP-11 relay information, nostr-tools. Relay operation, retention and access policies may change; requests that require authentication or are refused are not bypassed.