Simply enter a list of names and spin the wheel to pick a random name.
Transform your giveaways, contests, and selections with our professional-grade wheel of names. Trusted by educators, marketers, and event organizers worldwide.
Join hundreds of thousands making random selections fair and fun! 🎡
From 100 names (Free) to 1 million names (Boost $29/mo)
Import names from CSV files instantly
Upload your own background images
Create and save as many wheels as you need
Share winner pages with anyone
Access complete spin history forever
Programmatic control with REST API (Boost+)
Secure authentication for your integrations
Spin wheels directly in your Discord server
Need forms, quizzes, or comment picker? View all plans
Join industry leaders who use Uplup to engage millions of users worldwide
Create wheels, add entries, trigger spins, retrieve winners, and manage saved wheels programmatically
SDKs for JavaScript, Python, PHP, Ruby, Go, and more.
Create, spin, and manage wheels programmatically.
Encrypted keys, IP whitelisting, audit logs.
Spin wheels directly in your Discord server with animated GIFs
Watch the wheel spin in real-time with animated GIFs right in Discord.
Spin with server members, roles, voice channel users, or reactions.
Run reaction-based giveaways with transparent winner selection.
Self-hosted bot with optional Uplup API integration for saved wheels
Everything you need to know about our Random Name Picker tool
The Random Name Picker wheel uses a fully client-side, transparent, and auditable winner selection process. This documentation details exactly how winners are selected to ensure complete fairness and transparency.
Every single name in your list has an equal chance of being selected, regardless of how many names are displayed on the wheel.
Winner selection happens entirely in your browser using cryptographically secure random number generation.
The selection algorithm is open, auditable, and can be independently verified.
The winner selection uses the Web Crypto API's crypto.getRandomValues()function, which provides cryptographically strong random values suitable for cryptographic operations.
// Cryptographically secure random selection
function selectWinner(allNames) {
// Generate random value using Web Crypto API
const array = new Uint32Array(1);
crypto.getRandomValues(array);
// Convert to index in the full list
const randomValue = array[0] / (0xffffffff + 1);
const winnerIndex = Math.floor(randomValue * allNames.length);
return allNames[winnerIndex];
}For performance reasons, the wheel displays a maximum of 250 segments. However, this is purely visual and does not affect the selection process.
// Example with 10,000 names
const allNames = [...]; // Full list of 10,000 names
const displayNames = allNames.slice(0, 250); // Only 250 shown on wheel
// Winner selection uses ALL names
const winner = selectFromFullList(allNames); // Selects from all 10,000
// After selection, update display
const winnerSegment = displayNames.includes(winner)
? displayNames.indexOf(winner)
: addWinnerToDisplay(winner);All names are loaded into memory, regardless of quantity.
// Load all names from database or input
const allNames = await loadAllNames(); // Could be 10, 100, or 100,000+ names
console.log(`Total names loaded: ${allNames.length}`);Duration is intelligently scaled based on user preference and list size.
// Duration scales with both preference and list size
const durationSettings = {
short: { baseMin: 2, baseMax: 4, scaleMin: 0.5, scaleMax: 0.75, cap: 7 },
normal: { baseMin: 3, baseMax: 8, scaleMin: 0.5, scaleMax: 1, cap: 12 },
long: { baseMin: 15, baseMax: 20, scaleMin: 1, scaleMax: 2.5, cap: 30 }
};
// Scale based on number of names (capped at 4000+)
const scaleFactor = Math.min(names.length / 1000, 4);
const minDuration = (setting.baseMin + scaleFactor * setting.scaleMin) * 1000;
const maxDuration = Math.min(setting.baseMax + scaleFactor * setting.scaleMax, setting.cap) * 1000;
// Examples for 5000 names:
// Short: 3.5-7 seconds | Normal: 5-12 seconds | Long: 20-30 secondsMultiple cryptographically secure random values are generated for duration and winner selection.
// Use Web Crypto API for all randomness
const array = new Uint32Array(2);
crypto.getRandomValues(array);
// First value: Determine exact spin duration within range
const randomDurationMs = minDuration + ((array[0] / 0xFFFFFFFF) * (maxDuration - minDuration));
// Second value: Will be used for winner selection
const randomValue = array[1] / (0xffffffff + 1); // Value between 0 and 1The random number determines which name from the full list wins.
// Select winner from complete list
const winnerIndex = Math.floor(randomValue * allNames.length);
const winner = allNames[winnerIndex];
console.log(`Winner selected: ${winner} (index ${winnerIndex} of ${allNames.length})`);The wheel spins for the determined duration and lands on the selected winner.
// Spin wheel for calculated duration
spinWheel(randomDurationMs);
// Update wheel display to show winner
if (displayedNames.includes(winner)) {
// Winner is visible on wheel - spin to it
spinToSegment(displayedNames.indexOf(winner));
} else {
// Winner not visible - add temporarily for display
const tempWheel = [...displayedNames.slice(0, 249), winner];
spinToSegment(249); // Spin to the winner's position
}For large CSV uploads, the system uses an optimized client-side index-based selection that can handle unlimited names efficiently.
// CSV files are stored in database with row indices
// Client selects winner by random index, then fetches just that name
class CSVWinnerSelector {
async selectWinner(csvBatchId, totalCount) {
// 1. Generate random index (0 to totalCount-1)
const randomIndex = Math.floor(Math.random() * totalCount);
// 2. Check if index is excluded (removed winner)
if (this.excludedIndices.has(randomIndex)) {
return this.selectWinner(csvBatchId, totalCount); // Retry
}
// 3. Fetch only that specific name from database
const response = await fetch('/api/get_csv_name_by_index', {
params: { csv_batch_id: csvBatchId, row_index: randomIndex }
});
// 4. Return the winner
return { name: response.data.name, index: randomIndex };
}
}When you remove a winner in CSV mode, the system tracks it client-side to ensure fair subsequent selections:
// Exclusion tracking for removed names
class ExclusionTracker {
constructor() {
this.excludedIndices = new Set(); // Removed row indices
this.excludedNames = new Set(); // Removed name strings
}
removeWinner(name, csvIndex) {
this.excludedIndices.add(csvIndex); // Skip this index
this.excludedNames.add(name); // Skip this name value
this.saveToLocalStorage(); // Persist for session
}
isExcluded(index, name) {
return this.excludedIndices.has(index) ||
this.excludedNames.has(name);
}
}When developer tools are open, the selection process logs detailed information:
// Sample console output for verification
"🎰 Spin Mode: NORMAL | Names: 10,000"
"⏱️ Duration range: 5.0s - 12.0s"
"=== WINNER SELECTION STARTING ==="
"Total names in full list: 10000"
"Names displayed on wheel: 250"
"Spin duration: 8.743s (randomly selected)"
"Random value generated: 0.7234567"
"Winner index: 7234 of 10000"
"Winner selected: John Smith"
"Winner in displayed names: false"
"=== SELECTION COMPLETE ==="crypto.getRandomValues() - the same randomness used for encryptionMath.random() is not cryptographically secure and could theoretically be predicted. We use the Web Crypto API to ensure true randomness suitable for contests, giveaways, and any scenario requiring verifiable fairness.
Every name has exactly equal probability of being selected:
// For a list of N names:
Probability per name = 1/N
// Examples:
100 names: Each has 1% chance
1,000 names: Each has 0.1% chance
10,000 names: Each has 0.01% chanceThe Random Name Picker ensures complete fairness by selecting from ALL names in your list using cryptographically secure randomness. The 250-segment wheel limit is purely visual and does not affect the selection process. Every name has an exactly equal chance of being selected, regardless of list size or display limitations.
This transparent, auditable process ensures your contests, giveaways, and selections are provably fair and can withstand any scrutiny.
// Create and spin a wheel
const response = await fetch('https://api.uplup.com/api/wheel/wheels', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('YOUR_API_KEY:YOUR_API_SECRET'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
wheel_name: 'Giveaway',
entries: ['Alice', 'Bob', 'Charlie']
})
});
const { data } = await response.json();
const wheel_id = data.wheel_id;
// Spin the wheel
const spinResponse = await fetch(`https://api.uplup.com/api/wheel/wheels/${wheel_id}/spin`, {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('YOUR_API_KEY:YOUR_API_SECRET'),
'Content-Type': 'application/json'
}
});
const spinData = await spinResponse.json();
console.log('Winner:', spinData.data.winner);npm install and npm start. The README has step-by-step instructions./spin reactions message_id:YOUR_MESSAGE_ID, 4) The bot generates an animated wheel with all reactors and picks a winner! You can filter by specific emoji using the emoji option.color option with 5 themes: Uplup (purple/pink - default), Vibrant (bold, bright colors), Pastel (soft, light colors), Sunset (warm oranges and pinks), Ocean (cool blues and teals). The animated GIF wheel spin uses your chosen theme.Our support team is here to help you get the most out of your Random Name Picker