JavaScript exposes two practical ways to generate random numbers: the Math.random() built-in, which returns a floating-point value in the half-open range [0, 1), and the browser's Crypto.getRandomValues() method, which fills a typed array with cryptographically strong integers drawn from the operating system. Neither function returns a usable integer in a custom inclusive range out of the box, so most production code wraps the raw output with a mapping step that scales the value up, floors it, and adjusts the offset. The most common pattern for integers from min to max is Math.floor(Math.random() * (max - min + 1)) + min, but a naive modulo on top of that pattern is biased whenever the random range does not divide evenly into the target range. For unbiased draws the cleanest approach is rejection sampling: pull a 32-bit value from Web Crypto, discard any value that lands in the incomplete tail, and accept the rest before mapping it into the requested inclusive range. Local browser tools such as the Random Number Generator apply that same technique so you can pull up to 1,000 inclusive integers without writing any JavaScript yourself.

Two Ways JavaScript Produces Random Values
JavaScript's built-in random source is Math.random(), a static method on the Math object that returns a floating-point pseudo-random number greater than or equal to 0 and strictly less than 1. The value is generated by the JavaScript engine using a seed-based algorithm; the ECMAScript specification only requires that the output look statistically random, not that it be unpredictable. That makes Math.random() fine for games, UI variations, sample data, and casual draws, but not appropriate for security tokens, passwords, or any setting where an attacker should not be able to reproduce the output.
The other option lives on the global Crypto object exposed by browsers: crypto.getRandomValues(), defined in the W3C Web Cryptography API. You hand it a typed array such as a Uint32Array or Uint8Array, and the browser fills it with random bits drawn from the operating system's cryptographic entropy source. The W3C specification at https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues and the MDN reference at MDN's getRandomValues documentation describe the same contract: the returned values are uniformly distributed across the range of the typed array. The catch is that the function is array-based, so you must read the numbers out of the buffer yourself.
| Property | Math.random() | Crypto.getRandomValues() |
|---|---|---|
| Output type | Number in [0, 1) | Integers filling a typed array |
| Source of randomness | Engine-internal pseudo-random generator | Operating system cryptographic entropy |
| Suitable for security | No | Yes, per the W3C specification |
| Range control | None built in; you scale and floor | None built in; you scale, mask, or reject |
| Browser support | Widely available in browsers | Widely available in modern browsers, secure context required |
Build an Inclusive Integer Range With Math.random
The simplest JavaScript recipe for an integer from min to max inclusive is to combine three operations: multiply, floor, and offset. The expression is written as a single line: const n = Math.floor(Math.random() * (max - min + 1)) + min;
The expression works in three stages. First, (max - min + 1) gives the count of integers in the inclusive range. Second, multiplying by Math.random() scales that count into a float in [0, count). Third, Math.floor truncates the float down to an integer offset that is added to min. With min = 1 and max = 10, the formula becomes Math.floor(Math.random() * 10) + 1; if Math.random() returned 0.4732, the result is Math.floor(4.732) + 1 = 4 + 1 = 5. That single arithmetic chain is the entire pattern you need for an inclusive integer in JavaScript.
Wrapped in a reusable function, the same pattern becomes function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }. Call it once for a single value or inside a loop for a batch. Every draw is independent, so the same number can appear twice in a row if the range is small, which is exactly what you want for dice rolls, sampling with replacement, or repeated experiments.
- Decide your inclusive minimum and maximum values; negative bounds are supported as long as both endpoints and the inclusive range size fit inside JavaScript's safe-integer range.
- Call Math.random() to get a uniform float in [0, 1).
- Multiply the result by (max - min + 1) to scale it up to the count of integers in the range.
- Apply Math.floor() to drop the fractional part and produce an integer offset.
- Add min so the offset starts at the lower bound rather than at zero.
- Store or print the integer; call the function again for additional independent draws.
How Modulo Mapping Skews Range Sampling
A common shortcut is Math.floor(Math.random() * max) % range, or its Web Crypto cousin that pulls a 32-bit word and writes word % range. Both look correct at a glance, but they are biased whenever the random range is not an exact multiple of the target range. Imagine a four-sided random output projected onto a three-sided target: values 0 and 1 map cleanly to 0 and 1, but values 2 and 3 both collapse onto 2, doubling the chance of 2 appearing. Over thousands of draws the distortion becomes visible, and any small range that does not divide evenly into a power of two is vulnerable.
The fix is rejection sampling. The generator pulls a raw value, checks whether it falls inside the incomplete tail at the top of the modulo range, and rejects it if so; only values that map one-to-one onto a target slot are accepted. Each accepted integer receives the same number of possible raw values, so the final distribution is uniform. The same trick scales up to large ranges by widening the raw pool and rejecting any value at or above the largest exact multiple of the target range that fits inside the source. That is why a well-implemented random integer generator never relies on a single modulo step.
Generate Random Numbers in JavaScript Without Writing Code
For readers who want the same unbiased behavior without writing a helper function, the Random Number Generator runs in the current browser, applies rejection sampling on top of Web Crypto, and never sends the bounds or the results to a server. The workflow is the same three steps regardless of whether you need one value or a batch, and the output is a plain comma-separated list that you can copy directly into another program.
- Enter the minimum and maximum safe integers; both endpoints can appear in the output, and negative bounds are allowed when the inclusive range size is itself a safe integer.
- Choose a result count between 1 and 1,000, then decide whether duplicate numbers are allowed for this draw.
- Select Generate numbers and review the comma-separated list, which you can select and copy with one click.
Changing any input clears the previous list, so the output on screen always reflects the current settings. If you request more unique values than the range contains, for example five unique values from 1 to 3, the generator reports the request as impossible instead of silently returning a shorter list. Inputs are also rejected for blank fields, reversed bounds, decimals, infinity, and unsafe integers outside the JavaScript safe-integer range, so the error is visible rather than hidden behind rounded bounds.
Choosing the Right Range Settings
The duplicate toggle changes the algorithm but not the underlying randomness. With duplicates enabled, every draw is independent and the same number can appear several times, which is the right choice for repeated simulations, dice rolls, or any experiment where earlier results should remain eligible. With duplicates disabled, a sparse partial Fisher-Yates shuffle picks unique offsets in O(count) memory, so selecting 10 distinct values from 1 to 100 produces 10 different integers with no repeats, which is the right choice for raffles, sample selection, or numbered participant orderings.
The 1,000-result ceiling is a memory and clarity safeguard, not an attempt to be a complete audit tool. Larger jobs should be split into batches, and any consequential drawing, including a regulated raffle, a security token, or an access-control decision, should follow your organization's audited procedure. The generator intentionally publishes no seed, signed transcript, or external randomness beacon, so a visitor cannot later prove which browser entropy produced a particular list. It is designed for classroom activities, drawings, randomized test data, order selection, and game setup, where convenience and uniform distribution matter more than cryptographic verifiability.
| Duplicate setting | When to use it | Example |
|---|---|---|
| Enabled (with replacement) | Repeated simulations, dice rolls, sampling where earlier results stay eligible | 5 draws from 1 to 6 can include the same number twice |
| Disabled (without replacement) | Selecting distinct positions, identifiers, numbered participants, randomized orderings | 5 unique draws from 1 to 20 produce 5 different integers |
| Count equals range size with duplicates off | Produce a unique randomized ordering of every integer in the range | Set count to 10 with min 1 and max 10 for a complete permutation |
Where These Random Numbers Are Useful
The same unbiased integer generator covers a wide spread of everyday tasks. Classroom teachers pull student numbers for cold-call questions, small businesses draw raffle winners for internal events, QA engineers seed randomized test data without writing a fixture, board-game hosts roll initiative order, and writers or game masters randomize loot tables or NPC choices. None of those uses requires cryptographic randomness, but all of them benefit from a uniform distribution so that no slot in the range is favored over another.
For tasks that need a different surface, such as picking a name from a typed list, spinning a wheel, rolling multiple dice at once, or generating a coin flip, the linked tools below handle each shape directly. Pair them with the Random Number Generator whenever you need a controlled integer range rather than a name, a die face, or a yes or no decision, so that each tool stays focused on the shape of randomness you actually need.
- Random Name Picker Wheel — pick a random winner from a typed list with a fair spin.
- Dice Roller — roll d4 through d20 or any custom die without keeping physical pieces.
- Coin Flip — flip a fair virtual coin powered by the same browser Web Crypto source.
For readers who want the same numeric approach in another language or sheet, the practical guides below walk through the equivalent recipes in C++ and Excel so the pattern can be ported without rewriting the algorithm from scratch.
- How to Generate Random Numbers in C++ (Quick Guide) — translate the same pattern into std::uniform_int_distribution.
- Generate Random Numbers in Excel Within a Range (3 Ways) — use RANDBETWEEN and related functions inside a spreadsheet.