Randomness comes from crypto.getRandomValues, the secure generator built into modern browsers, rather than the predictable Math.random. Values are drawn with rejection sampling so no character is favoured. The tool takes one character from every set you ticked, fills the remaining places from all ticked sets combined, then shuffles the order with a Fisher-Yates shuffle.
The pools hold 26 uppercase letters, 26 lowercase letters, 10 digits and 27 symbols (! @ # $ % ^ & * ( ) - _ = + [ ] { } ; : , . < > ? / ~), 89 characters in all. The look-alike option removes O and I, l, and 0 and 1, leaving 84. The entropy figure is the length times log2 of the pool size:
| Setting | Calculation | Shown as |
|---|
| 16 characters, all four sets | 16 x log2(89) | About 104 bits, very strong |
| 20 lowercase letters only | 20 x log2(26) | About 94 bits, very strong |
| 12 digits only | 12 x log2(10) | About 40 bits, fair |
The labels are: under 40 weak, 40 to 59 fair, 60 to 89 strong, 90 and above very strong. Because one character per set is placed deliberately, the true figure is marginally below the formula, which does not change the rating in practice.
To put the numbers in context, each extra character in the all-sets setting multiplies the number of possible passwords by 89, so going from 16 to 17 characters makes guessing 89 times harder. The figure only describes a password that came straight from the generator. If you alter it by hand, or reuse it, the number no longer applies, and a strong password typed into a fake login page is still lost. Generating several at once is fine: each one is an independent draw, so you may pick whichever you like.
The ticked sets matter more than they seem. With only Numbers ticked, a 16 character result is about 53 bits, far weaker than 16 characters from all four sets at 104 bits, even though both have the same length. If the note under the result says weak or fair for an account that matters, add length or tick more sets.