PickRandom LogoPickRandom

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).

Query parameters for /api/v1/number
ParameterTypeDefaultDescription
mininteger1Lower bound (inclusive), within ±10^15.
maxinteger100Upper bound (inclusive), within ±10^15; must be ≥ min.
countinteger1How many numbers to draw, 1–1000.
uniquebooleanfalseDraw 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.

JSON body for /api/v1/pick
ParameterTypeDefaultDescription
itemsstring[]required1–10,000 strings; total payload ≤ 1 MB.
countinteger1How many items to pick, 1–1000.
uniquebooleantrueNo 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).

JSON body for /api/v1/shuffle
ParameterTypeDefaultDescription
itemsstring[]required1–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.

Query parameters for /api/v1/coin
ParameterTypeDefaultDescription
countinteger1How 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.

Query parameters for /api/v1/dice
ParameterTypeDefaultDescription
sidesinteger6One of 2, 4, 6, 8, 10, 12, 20, 100.
countinteger1How 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.

Query parameters for /api/v1/yes-or-no
ParameterTypeDefaultDescription
maybebooleanfalseInclude “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.

Query parameters for /api/v1/password
ParameterTypeDefaultDescription
lengthinteger16Password length, 4–256.
uppercasebooleantrueInclude A–Z.
lowercasebooleantrueInclude a–z.
numbersbooleantrueInclude 0–9.
symbolsbooleantrueInclude 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
}

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.

JSON body for /api/v1/draw/reveal
ParameterTypeDefaultDescription
sealstringrequiredThe seal from /api/v1/draw/commit, unchanged (at most 4,096 characters).
commitmentstringrequiredThe published commitment — a 64-character lowercase hex string.
itemsstring[]required1–10,000 strings; total payload ≤ 1 MB. Order matters — it is part of the HMAC message.
client_seedstring""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 7 tools:

pick_random · shuffle · random_number · flip_coin · roll_dice · yes_or_no · generate_password

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}
  }}'