Use Cases & Code Examples
This guide shows how to integrate rng.dev into your applications with examples in Python, JavaScript, and Go.
Gaming & Gambling
Online games and gambling platforms need verifiable randomness that players can trust. The beacon provides:
- Verifiability: Players can independently verify every roll
- Unbiasability: No party (including the operator) can manipulate outcomes
- Audit trail: Complete history of all randomness used
Python Example: Dice Game
import httpx
from datetime import datetime, timezone
class VerifiableDiceGame:
"""A dice game where every roll is verifiable."""
BASE_URL = "https://rng.dev/api/v1"
def __init__(self, api_key: str | None = None):
self.headers = {}
if api_key:
self.headers["Authorization"] = f"Bearer {api_key}"
def get_roll(self) -> dict:
"""Get the current die roll with verification data."""
response = httpx.get(
f"{self.BASE_URL}/current",
headers=self.headers
)
response.raise_for_status()
return response.json()
def verify_roll(self, round_number: int) -> dict:
"""Fetch historical roll for verification."""
response = httpx.get(
f"{self.BASE_URL}/round/{round_number}",
headers=self.headers
)
response.raise_for_status()
return response.json()
def play_round(self, player_bet: int) -> dict:
"""Play a round: player bets on a number 1-6."""
if not 1 <= player_bet <= 6:
raise ValueError("Bet must be between 1 and 6")
# Get verifiable roll
roll = self.get_roll()
return {
"bet": player_bet,
"roll": roll["die_value"],
"won": player_bet == roll["die_value"],
"round": roll["round"],
"verification_url": f"https://rng.dev/verify/{roll['round']}"
}
# Usage
game = VerifiableDiceGame(api_key="rng_sk_your_key_here")
result = game.play_round(player_bet=4)
print(f"You bet {result['bet']}, rolled {result['roll']}")
print(f"Verify at: {result['verification_url']}")
JavaScript Example: Browser-Based Game
class VerifiableDiceGame {
constructor(apiKey = null) {
this.baseUrl = 'https://rng.dev/api/v1';
this.headers = apiKey
? { 'Authorization': `Bearer ${apiKey}` }
: {};
}
async getRoll() {
const response = await fetch(`${this.baseUrl}/current`, {
headers: this.headers
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
async playRound(playerBet) {
if (playerBet < 1 || playerBet > 6) {
throw new Error('Bet must be between 1 and 6');
}
const roll = await this.getRoll();
return {
bet: playerBet,
roll: roll.die_value,
won: playerBet === roll.die_value,
round: roll.round,
verificationUrl: `https://rng.dev/verify/${roll.round}`
};
}
}
// Usage
const game = new VerifiableDiceGame();
const result = await game.playRound(4);
console.log(`You bet ${result.bet}, rolled ${result.roll}`);
console.log(`Verify at: ${result.verificationUrl}`);
Go Example: Server-Side Integration
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type BeaconClient struct {
BaseURL string
APIKey string
Client *http.Client
}
type RoundResponse struct {
Round int `json:"round"`
OutputHash string `json:"output_hash"`
DieValue int `json:"die_value"`
Status string `json:"status"`
}
func NewBeaconClient(apiKey string) *BeaconClient {
return &BeaconClient{
BaseURL: "https://rng.dev/api/v1",
APIKey: apiKey,
Client: &http.Client{},
}
}
func (c *BeaconClient) GetCurrentRoll() (*RoundResponse, error) {
req, err := http.NewRequest("GET", c.BaseURL+"/current", nil)
if err != nil {
return nil, err
}
if c.APIKey != "" {
req.Header.Set("Authorization", "Bearer "+c.APIKey)
}
resp, err := c.Client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var round RoundResponse
if err := json.NewDecoder(resp.Body).Decode(&round); err != nil {
return nil, err
}
return &round, nil
}
func main() {
client := NewBeaconClient("rng_sk_your_key_here")
roll, err := client.GetCurrentRoll()
if err != nil {
panic(err)
}
fmt.Printf("Round %d: rolled %d\n", roll.Round, roll.DieValue)
fmt.Printf("Verify: https://rng.dev/verify/%d\n", roll.Round)
}
Machine Learning & AI
ML training requires reproducible randomness for:
- Model initialization: Same seed = same starting weights
- Data shuffling: Reproducible train/test splits
- Hyperparameter search: Fair comparison between runs
Python Example: Reproducible Training
import httpx
import hashlib
import numpy as np
class BeaconRNG:
"""Reproducible RNG seeded from rng.dev beacon."""
def __init__(self, round_number: int):
"""Initialize with a specific beacon round for reproducibility."""
self.round_number = round_number
self.seed = self._fetch_seed(round_number)
self.rng = np.random.default_rng(self.seed)
def _fetch_seed(self, round_number: int) -> int:
"""Fetch and convert beacon hash to numpy seed."""
response = httpx.get(f"https://rng.dev/api/v1/round/{round_number}")
response.raise_for_status()
output_hash = response.json()["output_hash"]
# Use first 8 bytes of hash as seed
seed_bytes = bytes.fromhex(output_hash[:16])
return int.from_bytes(seed_bytes, 'big')
def shuffle(self, data: list) -> list:
"""Shuffle data reproducibly."""
indices = self.rng.permutation(len(data))
return [data[i] for i in indices]
def train_test_split(self, data: list, test_ratio: float = 0.2):
"""Split data into train/test sets."""
shuffled = self.shuffle(data)
split_idx = int(len(shuffled) * (1 - test_ratio))
return shuffled[:split_idx], shuffled[split_idx:]
def random_weights(self, shape: tuple) -> np.ndarray:
"""Generate random weights for model initialization."""
return self.rng.standard_normal(shape) * 0.01
# Usage: reproducible experiment
BEACON_ROUND = 12345678 # Document this for reproducibility
rng = BeaconRNG(round_number=BEACON_ROUND)
# Same round = same results every time
data = list(range(1000))
train, test = rng.train_test_split(data, test_ratio=0.2)
print(f"Experiment seeded from beacon round {BEACON_ROUND}")
print(f"Train size: {len(train)}, Test size: {len(test)}")
print(f"Verify seed: https://rng.dev/verify/{BEACON_ROUND}")
Logging for Reproducibility
import json
from datetime import datetime
def log_experiment(experiment_name: str, beacon_round: int, results: dict):
"""Log experiment with beacon reference for reproducibility."""
log_entry = {
"experiment": experiment_name,
"timestamp": datetime.utcnow().isoformat() + "Z",
"randomness": {
"source": "rng.dev",
"round": beacon_round,
"verification_url": f"https://rng.dev/verify/{beacon_round}"
},
"results": results
}
# Anyone can reproduce by using the same beacon round
with open(f"experiments/{experiment_name}.json", "w") as f:
json.dump(log_entry, f, indent=2)
return log_entry
# Usage
results = {"accuracy": 0.95, "f1_score": 0.93}
log_experiment("bert_finetuning_v3", beacon_round=12345678, results=results)
Governance & Selection
Fair selection processes for juries, auditors, committees, or giveaways.
Python Example: Fair Lottery
import httpx
import hashlib
from typing import TypeVar
T = TypeVar('T')
class FairSelector:
"""Verifiable random selection for governance."""
def __init__(self, round_number: int):
"""
Initialize selector with a future beacon round.
IMPORTANT: Commit to using this round BEFORE it's generated.
This ensures no one can influence the selection.
"""
self.round_number = round_number
self._beacon_data = None
def _fetch_beacon(self) -> dict:
"""Fetch beacon data (cached after first call)."""
if self._beacon_data is None:
response = httpx.get(
f"https://rng.dev/api/v1/round/{self.round_number}"
)
response.raise_for_status()
self._beacon_data = response.json()
return self._beacon_data
def select(self, candidates: list[T], count: int = 1) -> list[T]:
"""
Select `count` items from candidates using beacon randomness.
Selection is deterministic given the beacon round.
"""
if count > len(candidates):
raise ValueError("Cannot select more than available candidates")
beacon = self._fetch_beacon()
output_hash = beacon["output_hash"]
# Create deterministic shuffled indices
selected = []
remaining = list(range(len(candidates)))
for i in range(count):
# Hash: output_hash + selection_index
selection_hash = hashlib.sha256(
f"{output_hash}:{i}".encode()
).hexdigest()
# Convert to index
index = int(selection_hash[:8], 16) % len(remaining)
selected.append(candidates[remaining.pop(index)])
return selected
def verification_proof(self) -> dict:
"""Generate proof for public verification."""
beacon = self._fetch_beacon()
return {
"beacon_round": self.round_number,
"beacon_hash": beacon["output_hash"],
"generated_at": beacon["generated_at"],
"verification_url": f"https://rng.dev/verify/{self.round_number}"
}
# Usage: Community grant selection
candidates = [
{"name": "Project Alpha", "id": "p001"},
{"name": "Project Beta", "id": "p002"},
{"name": "Project Gamma", "id": "p003"},
{"name": "Project Delta", "id": "p004"},
{"name": "Project Epsilon", "id": "p005"},
]
# Announce: "Winners will be selected using beacon round 12345678"
# Wait for that round to be generated...
selector = FairSelector(round_number=12345678)
winners = selector.select(candidates, count=2)
print("Selected winners:")
for winner in winners:
print(f" - {winner['name']}")
proof = selector.verification_proof()
print(f"\nVerify selection: {proof['verification_url']}")
Smart Contracts
Use beacon randomness in smart contracts by committing to future rounds.
Solidity Example: On-Chain Lottery
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/**
* @title BeaconLottery
* @notice Lottery using rng.dev beacon for verifiable randomness
*
* Flow:
* 1. Owner announces beacon round to use (in the future)
* 2. Players enter before that round is generated
* 3. After round is generated, anyone can submit the beacon hash
* 4. Winner is determined deterministically from hash
*/
contract BeaconLottery {
address public owner;
uint256 public beaconRound;
bytes32 public beaconHash;
address[] public players;
address public winner;
bool public entryClosed;
bool public resolved;
event PlayerEntered(address indexed player, uint256 playerIndex);
event LotteryResolved(address indexed winner, bytes32 beaconHash);
constructor(uint256 _beaconRound) {
owner = msg.sender;
beaconRound = _beaconRound;
}
function enter() external {
require(!entryClosed, "Entry closed");
require(!resolved, "Already resolved");
players.push(msg.sender);
emit PlayerEntered(msg.sender, players.length - 1);
}
function closeEntry() external {
require(msg.sender == owner, "Only owner");
entryClosed = true;
}
/**
* @notice Submit beacon hash after round is generated
* @param _beaconHash The output_hash from rng.dev/api/v1/round/{beaconRound}
*
* Note: In production, use an oracle or verify the hash on-chain
*/
function resolve(bytes32 _beaconHash) external {
require(entryClosed, "Entry not closed");
require(!resolved, "Already resolved");
require(players.length > 0, "No players");
beaconHash = _beaconHash;
// Deterministic winner selection from beacon hash
uint256 winnerIndex = uint256(beaconHash) % players.length;
winner = players[winnerIndex];
resolved = true;
emit LotteryResolved(winner, beaconHash);
}
function getVerificationUrl() external view returns (string memory) {
return string(
abi.encodePacked(
"https://rng.dev/verify/",
_uint2str(beaconRound)
)
);
}
function _uint2str(uint256 _i) internal pure returns (string memory) {
if (_i == 0) return "0";
uint256 j = _i;
uint256 length;
while (j != 0) { length++; j /= 10; }
bytes memory bstr = new bytes(length);
uint256 k = length;
while (_i != 0) {
k = k - 1;
bstr[k] = bytes1(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);
}
}
JavaScript: Off-Chain Verification
// Verify lottery fairness off-chain
async function verifyLottery(contractAddress, beaconRound) {
// 1. Fetch beacon data
const beaconResponse = await fetch(
`https://rng.dev/api/v1/round/${beaconRound}`
);
const beacon = await beaconResponse.json();
// 2. Get contract state (using ethers.js)
const contract = new ethers.Contract(contractAddress, abi, provider);
const players = await contract.players();
const winner = await contract.winner();
const contractHash = await contract.beaconHash();
// 3. Verify hash matches
const expectedHash = '0x' + beacon.output_hash;
if (contractHash.toLowerCase() !== expectedHash.toLowerCase()) {
throw new Error('Beacon hash mismatch!');
}
// 4. Verify winner calculation
const expectedWinnerIndex = BigInt(expectedHash) % BigInt(players.length);
const expectedWinner = players[Number(expectedWinnerIndex)];
if (winner.toLowerCase() !== expectedWinner.toLowerCase()) {
throw new Error('Winner calculation mismatch!');
}
return {
verified: true,
beaconRound,
beaconHash: beacon.output_hash,
totalPlayers: players.length,
winnerIndex: Number(expectedWinnerIndex),
winner,
verificationUrl: `https://rng.dev/verify/${beaconRound}`
};
}
Real-Time Applications
For applications needing continuous randomness updates.
JavaScript: SSE Streaming
class BeaconStream {
constructor(onRound, onError) {
this.onRound = onRound;
this.onError = onError;
this.eventSource = null;
}
connect() {
this.eventSource = new EventSource('https://rng.dev/api/v1/stream');
this.eventSource.addEventListener('round', (event) => {
const round = JSON.parse(event.data);
this.onRound(round);
});
this.eventSource.onerror = (error) => {
this.onError(error);
// Auto-reconnect after 5 seconds
setTimeout(() => this.connect(), 5000);
};
}
disconnect() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
}
}
}
// Usage: Live die roll display
const stream = new BeaconStream(
(round) => {
document.getElementById('die').textContent = round.die_value;
document.getElementById('round').textContent = round.round;
},
(error) => {
console.error('Stream error:', error);
}
);
stream.connect();
Python: Async Streaming
import aiohttp
import asyncio
import json
async def stream_beacon_rounds(callback):
"""Stream beacon rounds in real-time."""
async with aiohttp.ClientSession() as session:
async with session.get('https://rng.dev/api/v1/stream') as response:
async for line in response.content:
line = line.decode('utf-8').strip()
if line.startswith('event: round'):
continue
if line.startswith('data: '):
data = json.loads(line[6:])
await callback(data)
async def handle_round(round_data):
print(f"Round {round_data['round']}: {round_data['die_value']}")
# Usage
asyncio.run(stream_beacon_rounds(handle_round))
Batch Processing
For applications that need multiple random values.
Python: Batch Expansion
import httpx
import hashlib
def expand_beacon(round_number: int, count: int) -> list[int]:
"""
Expand a single beacon round into multiple die values.
Uses deterministic derivation: SHA3(output_hash || index) mod 6 + 1
"""
response = httpx.get(f"https://rng.dev/api/v1/round/{round_number}")
response.raise_for_status()
output_hash = response.json()["output_hash"]
values = []
for i in range(count):
# Derive child value
derived = hashlib.sha3_256(
f"{output_hash}:{i}".encode()
).hexdigest()
# Convert to die value (1-6) using rejection sampling
for j in range(0, len(derived), 2):
byte_val = int(derived[j:j+2], 16)
if byte_val < 252: # 252 = 6 * 42, avoids bias
values.append((byte_val % 6) + 1)
break
else:
# Fallback (extremely rare)
values.append((int(derived[:8], 16) % 6) + 1)
return values
# Generate 100 die values from one beacon round
values = expand_beacon(round_number=12345678, count=100)
print(f"Generated {len(values)} values: {values[:10]}...")
Best Practices
1. Always Verify
# Store verification data with your results
result = {
"outcome": selected_winner,
"beacon_round": round_number,
"beacon_hash": beacon_data["output_hash"],
"verification_url": f"https://rng.dev/verify/{round_number}"
}
2. Commit Before Reveal
# For high-stakes applications, announce the round BEFORE it's generated
announcement = {
"lottery_id": "spring-2026",
"beacon_round": current_round + 60, # ~1 minute in future
"announced_at": datetime.utcnow().isoformat()
}
publish(announcement) # Commit to using this round
3. Handle Rate Limits
import time
def fetch_with_retry(url: str, max_retries: int = 3) -> dict:
for attempt in range(max_retries):
response = httpx.get(url)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
continue
response.raise_for_status()
return response.json()
raise Exception("Max retries exceeded")
4. Use API Keys for Production
# Unauthenticated: 10 requests/hour
# Authenticated: 100,000 requests/day
client = httpx.Client(
base_url="https://rng.dev/api/v1",
headers={"Authorization": f"Bearer {api_key}"}
)
Further Reading
- REST API Reference — Complete API documentation
- Verification Guide — How to verify rounds
- Architecture — How the beacon works
- Statistical Tests — Randomness quality validation