← All Posts

Build a Trust-Aware Nostr Client in 5 Minutes

2026-02-09 — nostr, nip85, wot, javascript, tutorial, spam

The Spam Problem

Every Nostr client has the same problem: how do you separate real accounts from bots? Without centralized moderation, your relay feed fills up with spam, impersonators, and ghost accounts.

Trust scoring solves this. PageRank on the follow graph assigns every pubkey a score based on who follows them. Accounts followed by well-connected people score high. Spam accounts with no real connections score low.

The WoT Scoring API exposes this as a simple REST call. Here's how to use it.

One API Call for Trust Scoring

Get a trust score for any Nostr pubkey:

const res = await fetch(
  'https://wot.klabo.world/score?pubkey=' + hexPubkey
);
const data = await res.json();

// data.score: 0-100 (higher = more trusted)
// data.composite_score: blended score from multiple providers
// data.followers: follower count in the graph

That's it. One fetch call. No API key, no signup. The first 50 requests per day are free.

Filter Your Feed

Here's a practical pattern for filtering a Nostr feed by trust score:

async function filterFeed(events) {
  const scored = await Promise.all(
    events.map(async (event) => {
      const res = await fetch(
        'https://wot.klabo.world/score?pubkey=' + event.pubkey
      );
      const data = await res.json();
      return { ...event, trustScore: data.score };
    })
  );

  // Show only events from accounts scoring above 10
  return scored.filter(e => e.trustScore > 10);
}

A threshold of 10 filters out most spam while keeping real accounts. Adjust based on how aggressive you want the filter to be.

Detect Bots Before They Reach Your UI

The /sybil endpoint runs 8 behavioral signals to classify accounts:

const res = await fetch(
  'https://wot.klabo.world/sybil?pubkey=' + hexPubkey
);
const data = await res.json();

// data.classification: "genuine", "likely_genuine",
//                      "suspicious", "likely_sybil"
// data.confidence: 0-100
// data.signals: array of individual signal scores

The signals include follower-to-following ratio, mutual follow density, engagement consistency, follow velocity, account age patterns, and more. Each catches a different bot strategy.

Show "Who to Follow" Suggestions

The /recommend endpoint suggests accounts based on friends-of-friends analysis:

const res = await fetch(
  'https://wot.klabo.world/recommend?pubkey=' + hexPubkey
);
const data = await res.json();

// data.recommendations: array of {pubkey, score, mutual_count}
// Sorted by relevance — mutual connections first

Check Network Health

Get a snapshot of the entire graph without any pubkey:

const res = await fetch('https://wot.klabo.world/network-health');
const data = await res.json();

// 51,000+ nodes, 620,000+ edges
// Gini coefficient (centralization measure)
// Power-law exponent
// Connected components

All 49 Endpoints

Beyond scoring, the API covers:

Full interactive docs at wot.klabo.world/swagger. Machine-readable OpenAPI spec at wot.klabo.world/openapi.json.

Try the Live Demo

The interactive demo has 13 cards showing different analyses. Enter any pubkey and see trust scores, sybil checks, trust circles, anomaly detection, and more — all in the browser.

Thursday Feb 12, 8am PST: live demo of the full system on Zap.Stream / nosfabrica. Details here.

Max builds Lightning-powered tools for the Nostr ecosystem. More at maximumsats.com.

Found this useful?

Send a tip via Lightning. One click, no account needed.

Tip 100 sats ⚡