For developers & agents
PickRandom API
Every tool on this site is also a JSON endpoint. The API is free, requires no key or sign-up, and is CORS-open — call it straight from a browser, a script, a cron job, or an AI agent. All randomness is cryptographically secure (crypto.getRandomValues with rejection sampling — no modulo bias, no Math.random()), and responses are never cached.
There are no hard rate limits, so please be gentle: batch with the count parameter instead of looping single requests. Invalid input always returns HTTP 400 with a JSON {"error": "..."} body — the endpoints never fail with an HTML error page.
Prefer machine-readable docs? The full spec lives at /api/v1/openapi.json (OpenAPI 3.1), and a plain-text overview for AI agents is in /llms.txt.
Base URL — https://www.pickrandom.app
01
GET /api/v1/number
Random integers in an inclusive range. Set unique=true to draw without replacement (count must not exceed the range size).
| Parameter | Type | Default | Description |
|---|---|---|---|
| min | integer | 1 | Lower bound (inclusive), within ±10^15. |
| max | integer | 100 | Upper bound (inclusive), within ±10^15; must be ≥ min. |
| count | integer | 1 | How many numbers to draw, 1–1000. |
| unique | boolean | false | Draw without repeats. Requires count ≤ range size. |
Request
curl "https://www.pickrandom.app/api/v1/number?min=1&max=100&count=3&unique=true"
Response
{
"results": [42, 7, 88],
"min": 1,
"max": 100
}02
POST /api/v1/pick
Pick one or more random items from a list you send. Unique by default (a partial Fisher–Yates); set unique to false to allow repeats.
| Parameter | Type | Default | Description |
|---|---|---|---|
| items | string[] | required | 1–10,000 strings; total payload ≤ 1 MB. |
| count | integer | 1 | How many items to pick, 1–1000. |
| unique | boolean | true | No repeats. Requires count ≤ items.length. |
Request
curl -X POST "https://www.pickrandom.app/api/v1/pick" \
-H "Content-Type: application/json" \
-d '{"items": ["alice", "bob", "carol", "dave"], "count": 2}'Response
{
"results": ["carol", "alice"]
}03
POST /api/v1/shuffle
Return the whole list in a uniformly random order (unbiased Fisher–Yates).
| Parameter | Type | Default | Description |
|---|---|---|---|
| items | string[] | required | 1–10,000 strings; total payload ≤ 1 MB. |
Request
curl -X POST "https://www.pickrandom.app/api/v1/shuffle" \
-H "Content-Type: application/json" \
-d '{"items": ["red", "green", "blue"]}'Response
{
"results": ["blue", "red", "green"]
}04
GET /api/v1/coin
Fair 50/50 coin flips.
| Parameter | Type | Default | Description |
|---|---|---|---|
| count | integer | 1 | How many flips, 1–1000. |
Request
curl "https://www.pickrandom.app/api/v1/coin?count=3"
Response
{
"results": ["heads", "tails", "heads"]
}05
GET /api/v1/dice
Roll standard dice, from a d2 to a d100, with the total precomputed.
| Parameter | Type | Default | Description |
|---|---|---|---|
| sides | integer | 6 | One of 2, 4, 6, 8, 10, 12, 20, 100. |
| count | integer | 1 | How many dice to roll, 1–100. |
Request
curl "https://www.pickrandom.app/api/v1/dice?sides=20&count=2"
Response
{
"results": [17, 4],
"total": 21,
"sides": 20
}06
GET /api/v1/yes-or-no
An unbiased yes-or-no answer. Add maybe=true for a three-way split.
| Parameter | Type | Default | Description |
|---|---|---|---|
| maybe | boolean | false | Include “maybe” as a third, equally likely outcome. |
Request
curl "https://www.pickrandom.app/api/v1/yes-or-no"
Response
{
"result": "yes"
}07
GET /api/v1/password
A cryptographically secure password with at least one character from each enabled set. Generated per request and never stored or logged.
| Parameter | Type | Default | Description |
|---|---|---|---|
| length | integer | 16 | Password length, 4–256. |
| uppercase | boolean | true | Include A–Z. |
| lowercase | boolean | true | Include a–z. |
| numbers | boolean | true | Include 0–9. |
| symbols | boolean | true | Include punctuation symbols. At least one set must be enabled. |
Request
curl "https://www.pickrandom.app/api/v1/password?length=24&symbols=false"
Response
{
"result": "vN3kQ8pXbR2mW7cJ1sT5yZ0d",
"length": 24
}08
GET /api/v1/letter
Random letters A–Z. Case is uppercase, lowercase, or mixed (each letter's case chosen by a fair coin flip).
| Parameter | Type | Default | Description |
|---|---|---|---|
| count | integer | 1 | How many letters, 1–1000. |
| case | string | uppercase | One of uppercase, lowercase, mixed. |
| unique | boolean | false | Distinct letters only. Requires count ≤ 26. |
Request
curl "https://www.pickrandom.app/api/v1/letter?count=3&case=mixed"
Response
{
"results": ["K", "f", "Q"]
}09
GET /api/v1/color
Random colors, uniform over the 24-bit RGB space. Each result carries hex, rgb() and hsl() representations of the same color.
| Parameter | Type | Default | Description |
|---|---|---|---|
| count | integer | 1 | How many colors, 1–1000. |
Request
curl "https://www.pickrandom.app/api/v1/color?count=2"
Response
{
"results": [
{ "hex": "#D65076", "rgb": "rgb(214, 80, 118)", "hsl": "hsl(343, 62%, 58%)" },
{ "hex": "#45B8AC", "rgb": "rgb(69, 184, 172)", "hsl": "hsl(174, 45%, 50%)" }
]
}10
GET /api/v1/word
Random words from a curated, family-friendly list of ~1,600 common English words. Length buckets: short ≤ 4 letters, medium 5–7, long ≥ 8.
| Parameter | Type | Default | Description |
|---|---|---|---|
| count | integer | 1 | How many words, 1–1000. |
| length | string | any | One of any, short, medium, long. |
| capitalize | string | lowercase | One of lowercase, capitalized, uppercase. |
| unique | boolean | true | Distinct words only. Requires count ≤ pool size. |
Request
curl "https://www.pickrandom.app/api/v1/word?count=3&length=short"
Response
{
"results": ["mint", "arch", "glow"]
}11
GET /api/v1/date
Random UTC dates between start and end (both inclusive), returned sorted ascending. Add time=true for a random time of day.
| Parameter | Type | Default | Description |
|---|---|---|---|
| start | string | 2000-01-01 | Range start, YYYY-MM-DD (inclusive). |
| end | string | 2030-12-31 | Range end, YYYY-MM-DD (inclusive); must be ≥ start. |
| count | integer | 1 | How many dates, 1–1000. |
| unique | boolean | false | Distinct days only. Requires count ≤ days in range. |
| time | boolean | false | Append a random time of day (YYYY-MM-DDTHH:MMZ). |
Request
curl "https://www.pickrandom.app/api/v1/date?start=2026-01-01&end=2026-12-31&count=2&unique=true"
Response
{
"results": ["2026-03-14", "2026-09-02"],
"start": "2026-01-01",
"end": "2026-12-31"
}12
GET /api/v1/lottery
Lottery quick picks — unique, sorted numbers per line. Presets: powerball, mega-millions, euromillions, lotto-649; or game=custom with pool, pick, and optional bonus_pool.
| Parameter | Type | Default | Description |
|---|---|---|---|
| game | string | powerball | One of powerball, mega-millions, euromillions, lotto-649, custom. |
| lines | integer | 1 | How many lines, 1–100. |
| pool | integer | — | Custom games: main pool size, 2–999. |
| pick | integer | — | Custom games: main numbers per line, 1–pool. |
| bonus_pool | integer | 0 | Custom games: bonus-ball pool size; 0 for none. |
Request
curl "https://www.pickrandom.app/api/v1/lottery?game=powerball&lines=2"
Response
{
"results": [
{ "main": [7, 21, 34, 52, 68], "bonus": [14] },
{ "main": [3, 18, 40, 55, 61], "bonus": [9] }
],
"game": "powerball",
"config": { "mainCount": 5, "mainMax": 69, "bonusCount": 1, "bonusMax": 26 }
}13
GET /api/v1/uuid
RFC 4122 version 4 UUIDs from the platform CSPRNG.
| Parameter | Type | Default | Description |
|---|---|---|---|
| count | integer | 1 | How many UUIDs, 1–1000. |
Request
curl "https://www.pickrandom.app/api/v1/uuid?count=2"
Response
{
"results": [
"6f2b9a1e-8c3d-4e5f-9a70-1b2c3d4e5f60",
"0a1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d"
]
}14
GET /api/v1/float
Uniform random floats in [min, max) with 53 bits of entropy — or set gaussian=true for normally distributed samples (min/max are then ignored).
| Parameter | Type | Default | Description |
|---|---|---|---|
| min | number | 0 | Uniform mode: lower bound (inclusive). |
| max | number | 1 | Uniform mode: upper bound (exclusive); must be > min. |
| count | integer | 1 | How many floats, 1–1000. |
| gaussian | boolean | false | Sample a normal distribution instead. |
| mean | number | 0 | Gaussian mode: distribution mean. |
| stddev | number | 1 | Gaussian mode: standard deviation; must be > 0. |
Request
curl "https://www.pickrandom.app/api/v1/float?gaussian=true&mean=100&stddev=15&count=3"
Response
{
"results": [93.41180492, 112.87016371, 99.05122808],
"mean": 100,
"stddev": 15
}15
GET /api/v1/bytes
Raw cryptographically secure random bytes for tokens, salts, and seeds.
| Parameter | Type | Default | Description |
|---|---|---|---|
| length | integer | 32 | How many bytes, 1–1024. |
| encoding | string | hex | One of hex, base64. |
Request
curl "https://www.pickrandom.app/api/v1/bytes?length=16&encoding=base64"
Response
{
"result": "Zm9vYmFyYmF6cXV4MTIzNA==",
"length": 16,
"encoding": "base64"
}Provably fair
Verifiable draws
For raffles where participants should not have to trust the operator, the API offers a two-step commit–reveal draw: commit (the server generates a secret seed and returns its SHA-256 commitment), publish (you post the commitment where participants can see it, and optionally collect a client_seed from them), then reveal (the server opens the seed and derives the winner deterministically). Because the seed was committed before anyone saw the client seed, the server cannot re-roll — and the reveal response includes everything a third party needs to recompute the winner.
The protocol is stateless: nothing is stored server-side. The encrypted seal returned by commit is the state — send it back unchanged at reveal time. Note: these two endpoints return HTTP 503 on deployments where the DRAW_SECRET environment variable is not configured.
Step 01
POST /api/v1/draw/commit
No body required. Returns the commitment to publish and an opaque seal that only this server can open. Publish the commitment to participants before revealing.
Request
curl -X POST "https://www.pickrandom.app/api/v1/draw/commit"
Response
{
"commitment": "9f2ce2…64-char lowercase hex…41b7",
"seal": "wN3kQ…opaque base64, keep it for the reveal…Zg==",
"algorithm": { "name": "commit-reveal-hmac-sha256-v1", "…": "…" },
"expires": null,
"next": "POST /api/v1/draw/reveal",
"note": "Publish the commitment to participants BEFORE revealing."
}Step 02
POST /api/v1/draw/reveal
Opens the seal, verifies the seed still hashes to the published commitment, and derives the winner — revealing the server seed, the HMAC, and the exact formula for third-party audit.
| Parameter | Type | Default | Description |
|---|---|---|---|
| seal | string | required | The seal from /api/v1/draw/commit, unchanged (at most 4,096 characters). |
| commitment | string | required | The published commitment — a 64-character lowercase hex string. |
| items | string[] | required | 1–10,000 strings; total payload ≤ 1 MB. Order matters — it is part of the HMAC message. |
| client_seed | string | "" | Optional participant-contributed entropy (at most 256 characters), collected after the commitment was published. |
Request
curl -X POST "https://www.pickrandom.app/api/v1/draw/reveal" \
-H "Content-Type: application/json" \
-d '{
"seal": "wN3kQ…Zg==",
"commitment": "9f2ce2…41b7",
"items": ["alice", "bob", "carol"],
"client_seed": "tweet-1808991234"
}'Response
{
"winner": "carol",
"winnerIndex": 2,
"serverSeed": "e3d1a0…64-char lowercase hex…77af",
"commitment": "9f2ce2…41b7",
"clientSeed": "tweet-1808991234",
"algorithm": { "name": "commit-reveal-hmac-sha256-v1", "…": "…" },
"verify": {
"message": "9f2ce2…41b7\ntweet-1808991234\n[\"alice\",\"bob\",\"carol\"]",
"hmacHex": "5b09fc…64-char lowercase hex…c2d4",
"computation": "winnerIndex = BigInt(\"0x\" + hmacHex.slice(0, 16)) % BigInt(3) = 2, …"
}
}Verify it yourself
Anyone can audit a draw with three checks, no trust in this server required: the commitment equals sha256(serverSeed) (the 64-character hex string itself, not the decoded bytes); the HMAC message is commitment + "\n" + clientSeed + "\n" + JSON.stringify(items); and the winner index is the first 8 bytes of HMAC-SHA256(serverSeed, message) read as a big-endian unsigned 64-bit integer, mod the number of items.
The reveal response repeats this recipe in its algorithm and verify fields, so an auditor never needs this page.
Node.js — verification
import { createHash, createHmac } from "node:crypto";
// Inputs: the reveal response fields, plus the commitment you saw published.
const { serverSeed, clientSeed } = revealResponse;
const items = ["alice", "bob", "carol"]; // the exact list, in the exact order
// 1. The revealed seed must hash back to the published commitment.
// (The seed is a 64-char hex STRING — hash the string, not decoded bytes.)
const commitment = createHash("sha256").update(serverSeed).digest("hex");
// commitment === the one published before the draw ✓
// 2. Recompute the winner from the seed, the client seed, and the items.
const message = commitment + "\n" + clientSeed + "\n" + JSON.stringify(items);
const hmacHex = createHmac("sha256", serverSeed).update(message).digest("hex");
// 3. First 8 bytes of the HMAC as a big-endian unsigned 64-bit integer,
// reduced mod items.length.
const winnerIndex = Number(BigInt("0x" + hmacHex.slice(0, 16)) % BigInt(items.length));
// winnerIndex === revealResponse.winnerIndex ✓ items[winnerIndex] === winner ✓In your code
JavaScript & Python
No SDK needed — the API is plain HTTP and JSON. Here are the number and pick endpoints from JavaScript fetch and Python requests.
JavaScript — fetch
const res = await fetch(
"https://www.pickrandom.app/api/v1/number?min=1&max=100&count=5"
);
const { results } = await res.json();
console.log(results); // e.g. [42, 7, 88, 13, 66]const res = await fetch("https://www.pickrandom.app/api/v1/pick", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items: ["alice", "bob", "carol"], count: 1 }),
});
const { results } = await res.json();
console.log(results[0]); // e.g. "bob"Python — requests
import requests
res = requests.get(
"https://www.pickrandom.app/api/v1/number",
params={"min": 1, "max": 100, "count": 5},
)
print(res.json()["results"]) # e.g. [42, 7, 88, 13, 66]import requests
res = requests.post(
"https://www.pickrandom.app/api/v1/pick",
json={"items": ["alice", "bob", "carol"], "count": 1},
)
print(res.json()["results"][0]) # e.g. "bob"Use with AI agents
Built for tool calls
These endpoints are documented in /llms.txt and are safe to call from agent tools: every request is stateless and side-effect free, no authentication or key management is needed, CORS is open, and errors come back as machine-readable JSON with a 400 status. If your agent needs a fair coin flip, an unbiased pick, or a secure password, point it here instead of letting the model improvise randomness.
Model Context Protocol
MCP server
PickRandom is also an MCP server at POST /api/mcp — JSON-RPC 2.0 over streamable HTTP, fully stateless (no sessions, no authentication), with the same validation limits and CSPRNG outcomes as the REST endpoints. Point any MCP client at https://www.pickrandom.app/api/mcp and it gets 15 tools:
pick_random · shuffle · random_number · flip_coin · roll_dice · yes_or_no · generate_password · random_letter · random_color · random_word · random_date · lottery_numbers · generate_uuid · random_float · random_bytes
Add it to your MCP client configuration (Claude Code, Cursor, and friends) as a remote HTTP server:
{
"mcpServers": {
"pickrandom": {
"type": "http",
"url": "https://www.pickrandom.app/api/mcp"
}
}
}Initialize
curl -s "https://www.pickrandom.app/api/mcp" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {"name": "curl", "version": "0.0.0"}
}}'Call a tool
curl -s "https://www.pickrandom.app/api/mcp" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {
"name": "roll_dice",
"arguments": {"sides": 20, "count": 2}
}}'