How to Generate Random Strings in PowerShell

To generate a random string in PowerShell, turn a list of allowed characters into an array, pick characters with Get-Random in a loop, and join them with -join:

$chars  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.ToCharArray()
$random = -join (1..12 | ForEach-Object { Get-Random -InputObject $chars })
$random

Output (yours will differ):

HGRDWptVJXmX

That’s fine for test data and file names. For passwords, API keys or tokens, use the secure method further down, since Get-Random isn’t built for secrets.

I ran every example in PowerShell 7.6 and Windows PowerShell 5.1 and note the version-only options.

Two Get-Random mistakes to avoid

Get-Random picks from a list, and a plain string isn’t a list of characters. -Count also never picks the same item twice:

"Piping a plain string returns: $('ABCDEF' | Get-Random)"
"Piping its characters returns $(('ABCDEF'.ToCharArray() | Get-Random).ToString().Length) character"
"-Count 12 from 10 digits returns $(('0123456789'.ToCharArray() | Get-Random -Count 12).Count) characters"

Output:

Piping a plain string returns: ABCDEF
Piping its characters returns 1 character
-Count 12 from 10 digits returns 10 characters
PowerShell Get-Random returns the whole string and -Count never repeats
A string needs ToCharArray(), and -Count can’t exceed the list size (Windows PowerShell 5.1)

So -join ($chars | Get-Random -Count 12) never repeats a character, and it returns fewer than 12 when the set is small. Pick one character per loop instead, as in the first example.

A reusable random string function

This function guarantees at least one uppercase letter, one lowercase letter, one digit and, unless you turn them off, one symbol. It leaves out look-alike characters like I, l, O and 0:

function Get-RandomString {
    param(
        [int]$Length = 12,
        [switch]$NoSymbols
    )
    $sets = @('ABCDEFGHJKLMNPQRSTUVWXYZ', 'abcdefghijkmnopqrstuvwxyz', '23456789')
    if (-not $NoSymbols) { $sets += '!@#$%^&*-_' }

    $picked = foreach ($set in $sets) { Get-Random -InputObject $set.ToCharArray() }
    $all    = ($sets -join '').ToCharArray()
    $picked += 1..($Length - $sets.Count) | ForEach-Object { Get-Random -InputObject $all }

    -join ($picked | Get-Random -Count $picked.Count)
}

Get-RandomString
Get-RandomString -Length 8 -NoSymbols

Output (yours will differ):

@&s2LvLk_c$u
Yn96TyF9

The last line shuffles the result with Get-Random -Count, so the guaranteed characters don’t always sit at the start. In PowerShell 7 you can write Get-Random -Shuffle instead.

Get the same random values every time with -SetSeed

For tests and demos, -SetSeed makes Get-Random repeat the same sequence. I got the same results in both PowerShell versions:

"First run:  $(Get-Random -SetSeed 42 -Maximum 1000)"
"Second run: $(Get-Random -SetSeed 42 -Maximum 1000)"

$null = Get-Random -SetSeed 2026
$first = 'Alice', 'Bob', 'Carol', 'David', 'Emma'
$last  = 'Johnson', 'Smith', 'Diaz', 'Miller', 'Brown'
1..3 | ForEach-Object { '{0} {1}' -f (Get-Random -InputObject $first), (Get-Random -InputObject $last) }

Output:

First run:  177
Second run: 177
David Smith
Bob Brown
Alice Miller
PowerShell Get-Random -SetSeed repeats the same values
The same seed gives the same number and the same random names (PowerShell 7)

That’s handy for sample data like these random names, and it’s also why Get-Random shouldn’t produce secrets. Microsoft’s Get-Random documentation says it doesn’t ensure cryptographically secure randomness.

Generate a secure random string

For anything secret, use .NET’s RandomNumberGenerator. This function works in both PowerShell 7 and Windows PowerShell 5.1:

function New-SecureRandomString {
    param(
        [int]$Length = 20,
        [string]$Chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'
    )
    $rng   = [System.Security.Cryptography.RandomNumberGenerator]::Create()
    $byte  = [byte[]]::new(1)
    $limit = 256 - (256 % $Chars.Length)    # skip values that would favor some characters
    $out   = [System.Text.StringBuilder]::new()

    while ($out.Length -lt $Length) {
        $rng.GetBytes($byte)
        if ($byte[0] -lt $limit) { [void]$out.Append($Chars[$byte[0] % $Chars.Length]) }
    }
    $out.ToString()
}

New-SecureRandomString
New-SecureRandomString -Length 32

Output (yours will differ):

GKL7fxyKjEYxbsJ75MUj
T5YogG8tnR66ddYoqqQrjT4TEodVAwzE
PowerShell secure random string with RandomNumberGenerator
Cryptographically secure strings of 20 and 32 characters (PowerShell 7)

The $limit check throws away a few byte values so every character has the same chance. The RandomNumberGenerator reference explains the class.

PowerShell 7.4 and later: one line

On PowerShell 7.4 and later, which run on .NET 8 or newer, GetString does the same work in one call. It doesn’t exist in Windows PowerShell 5.1:

$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'
[System.Security.Cryptography.RandomNumberGenerator]::GetString($chars, 20)

Output in PowerShell 7 (yours will differ):

KwLJBvyAUuvirehQnW2c

The PowerShell password generator builds on this for passwords with rules.

Generate a random token or unique ID

For API keys and reset links, generate random bytes and encode them as hex or Base64:

$bytes = [byte[]]::new(32)
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)

$hex = -join ($bytes | ForEach-Object { $_.ToString('x2') })
"Hex token ($($hex.Length) characters): $hex"
"Base64 token: $([Convert]::ToBase64String($bytes))"

Output (yours will differ):

Hex token (64 characters): 0e30e4a9cc037cd30bc7695590a14e1ff72e95a4de08d3517e64c7d9a1943dac
Base64 token: DjDkqcwDfNMLx2lVkKFOH/culaTeCNNRfmTH2aGUPaw=

When you only need something unique, not secret, a GUID is simpler:

$id = [guid]::NewGuid().ToString('N').Substring(0, 12)
"Order reference: ORD-$($id.ToUpper())"

Output (yours will differ