The 30-second summary

Math.random() is a non-cryptographic PRNG seeded from process state. It's sub-microsecond fast and good enough for animations, jitter, demos, and toy code. It is not cryptographically strong, it is not reproducible across runtimes, and there is nothing about a Math.random() call a third party can ever verify.

Provable.io publishes a hash of the server seed before the draw, then reveals it — anyone can re-derive the result and prove it wasn't engineered.

Feature matrix

CapabilityProvable.ioMath.random()
Cryptographic strengthHMAC-SHA256 keyed streamNo — xorshift / similar PRNG, predictable from a few samples
Reproducible from seedYesNo — seed is internal and runtime-specific
Third-party verifiabilityYes — publish seed + hash, anyone re-derivesNo — invisible from outside the process
Pre-commitmentYes — serverHash published firstNo
Latency~tens of ms (network)Sub-microsecond (in-process)
Auditable historyYes — persisted, addressable by short IDNo
Best forAnything a user, auditor, or regulator might disputeAnimations, UI jitter, throwaway examples

When Math.random() is the right answer

Don't reach for an HTTP API when a non-cryptographic PRNG is exactly what you need:

When Provable.io is the right answer

The moment a result needs to be defensible, Math.random() stops being an option. Reach for Provable.io when:

Try it now

Same shape as Math.random(), returned over HTTP — except the response includes a serverHash anyone can verify.

curl "https://api.provable.io/api/floats?clientSeed=vs-math-random-demo&count=5"

FAQ

Is Math.random() seedable?

No, not in the JavaScript spec. Some libraries layer a seedable PRNG on top, but standard Math.random() gives you no control and no way for a third party to re-derive the output.

Why not just use a seeded PRNG library?

A seeded PRNG gives you reproducibility but not verifiability. A third party still has to trust that you ran it with the seed you claim. Provable.io commits the server seed hash before the call, which is the missing piece.

What about crypto.getRandomValues()?

That's the cryptographically strong in-process option — covered on its own page. See the comparison.

Next steps