Open pastebin, no login, paste text, get a link. That is the whole appeal, and it is also why every anonymous paste service turns into a dumping ground. Bots script the post endpoint and fire off thousands of spam links, phishing kits, leaked credential lists, malware config. The usual fix is to make the thing less anonymous: force an account, bolt on reCAPTCHA, rate-limit by IP. Every one of those punishes the honest one-off user to slow down a bot that just rotates IPs anyway.
I wanted a paste service that stayed anonymous and one-click but still cost a spammer something real. So the price of posting is not an account. It is energy. You either burn a little CPU (proof of work, free) or you pay 10 sats over Lightning. A human posting one snippet never notices. A bot posting ten thousand notices real fast.
Here is the whole flow against the live service at paste.powforge.dev. Every curl below is real and runs today.
The free path: prove work
Grab a challenge first.
curl -s https://paste.powforge.dev/api/challenge
# {"nonce":"468367dc78bff5e696e23d9ac1684417eda7d4ecb1d02030a0209e37ee28f953","difficulty":18}
You get a random nonce and a difficulty in bits. The job is to find any string solution where SHA-256(nonce + solution) starts with difficulty leading zero bits. That is it. No fancy VDF, just a hash you cannot shortcut, only grind.
Here is a solver you can drop in a file and run with plain Node, no dependencies.
const crypto = require('crypto');
function hasLeadingZeroBits(buf, bits) {
const fullBytes = Math.floor(bits / 8), rem = bits % 8;
for (let i = 0; i < fullBytes; i++) if (buf[i] !== 0) return false;
if (rem) {
const mask = (0xff << (8 - rem)) & 0xff;
if ((buf[fullBytes] & mask) !== 0) return false;
}
return true;
}
async function main() {
const ch = await (await fetch('https://paste.powforge.dev/api/challenge')).json();
let s = 0;
while (true) {
const h = crypto.createHash('sha256').update(ch.nonce + s).digest();
if (hasLeadingZeroBits(h, ch.difficulty)) break;
s++;
}
const solution = String(s);
const res = await (await fetch('https://paste.powforge.dev/api/paste', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: 'hello from proof of work', method: 'pow', nonce: ch.nonce, solution })
})).json();
console.log('https://paste.powforge.dev/' + res.id);
}
main();
Difficulty 18 took me about 150,000 hashes and 1.8 seconds on one core. Nobody waiting on a paste cares about two seconds. A spammer scripting the endpoint pays that tax on every single post, in wall-clock time, with no way to buy their way around it except the honest one below.
Post it and you get an id back.
# POST /api/paste { content, method:"pow", nonce, solution }
# -> {"id":"a06c33a7"}
curl -s https://paste.powforge.dev/a06c33a7
# ...
# ID: a06c33a7 | Method: Proof of Work | Expires: Sun, 16 Aug 2026 22:01:54 GMT
Proof-of-work pastes live 24 hours. Cheap to make, so they do not stick around forever.
The paid path: 10 sats, no CPU
Do not want to burn cycles? Pay instead. Same endpoint shape, you just ask for an invoice.
curl -s -X POST https://paste.powforge.dev/api/invoice \
-H 'Content-Type: application/json' \
-d '{"content":"paste that outlives the free tier"}'
# {"payment_hash":"acf00c5a...","bolt11":"lnbc100n1p4gpcwm..."}
Pay the bolt11 from any Lightning wallet, then poll until it clears.
curl -s https://paste.powforge.dev/api/check/acf00c5a...
Once paid the paste is created and kept for 30 days instead of 24 hours. The 10 sats is not the point, it is a fraction of a cent. The point is the same as the CPU: it is a real cost that scales with how much you post. One paste, you never feel it. A flood, and it adds up to actual money.
Why energy beats a login wall
Think about who each defense actually stops.
- Accounts stop nobody. Bots make accounts faster than people do. All you did was add friction for the honest user.
- CAPTCHA stops some bots and annoys every human, and the solving-farm market means a determined spammer just pays a fraction of a cent per solve.
- IP rate limits stop a lazy bot from one address and do nothing to a botnet or a proxy pool.
- Energy (PoW or sats) does not care who or where you are. It charges per post. It is the one cost a spammer cannot rotate their way out of, because it is not tied to identity at all.
That is the whole trick. Keep the service anonymous and one-click for the person posting one thing. Put a small, unavoidable, per-post cost in the way of the machine posting ten thousand. You do not need to know who anybody is. You just need posting to cost a little.
The service is live at paste.powforge.dev if you want to poke the endpoints yourself. Same pattern drops onto any write endpoint that bots abuse, not just pastes.
Top comments (0)