
Automate Active Directory User Creation from a CSV with PowerShell
Before you run this
This guide builds a PowerShell script that reads a CSV file of people and creates a matching Active Directory user account for each row — name, logon name, OU placement, and an initial password. Its purpose is to save you from clicking through Active Directory Users and Computers a hundred times when you onboard a class, a department, or a new office.
This changes your directory. Creating accounts is not destructive in the "delete data" sense, but it is a real write to AD that replicates to every domain controller, and a badly-scoped run can litter an OU with dozens of wrong accounts you then have to clean up. Treat it with respect.
Privileges: You need a session with rights to create user objects in the target OU — in practice an account with delegated user-creation rights on that OU, or a Domain Admin. You do not normally need to open PowerShell "as Administrator" for this (AD permissions are what matter, not local elevation), but you do need the ActiveDirectory module, which comes from RSAT on a workstation or the AD DS role tools on a server.
Test first. Read the script before you run it. Every New-ADUser here supports -WhatIf, and the first thing I show you is a dry run that creates nothing. Point it at a test OU with a two-row CSV before you ever aim it at real people. Do not paste-and-run a bulk-creation script blind against a live domain.
Assumptions I'm holding to:
- Windows Server 2019 or 2022, domain-joined, run from a DC or a management box with RSAT.
- Windows PowerShell 5.1 (the default) — this works identically in PowerShell 7 with the module imported.
- A single domain,
example.com. Substitute your own everywhere you see it.
The CSV
Keep the columns explicit and boring. Create C:\path\to\newusers.csv (your path):
FirstName,LastName,SamAccountName,Department,Title,OU
Ada,Lovelace,alovelace,Engineering,Analyst,"OU=Staff,DC=example,DC=com"
Alan,Turing,aturing,Engineering,Analyst,"OU=Staff,DC=example,DC=com"
A few rules that save pain later:
SamAccountNameis the pre-Windows-2000 logon name. It must be unique in the domain and 20 characters or fewer.- Quote the
OUvalue because it contains commas. It must be a real, existing OU distinguished name — the script does not create OUs. - I'm generating the UPN and email from
SamAccountName+@example.comin the script, so they're not in the CSV. If your UPN suffix differs, that's the one line to change.
The script
Save this as New-UsersFromCsv.ps1. It reads the CSV, skips any account that already exists, and creates the rest. I've kept the password handling deliberate — see the note below the code.
#Requires -Modules ActiveDirectory
param(
[string]$CsvPath = 'C:\path\to\newusers.csv', # your CSV
[string]$UpnSuffix = 'example.com', # your UPN / email domain
[switch]$WhatIf # pass -WhatIf for a dry run
)
Import-Module ActiveDirectory
# One shared initial password for this batch. Change it, and force a reset at first logon.
$initialPassword = Read-Host -Prompt 'Enter the initial password for this batch' -AsSecureString
$users = Import-Csv -Path $CsvPath
foreach ($u in $users) {
$sam = $u.SamAccountName.Trim()
# Skip anything that already exists so a re-run is safe.
if (Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue) {
Write-Warning "Skipping $sam - already exists."
continue
}
$upn = "$sam@$UpnSuffix"
$params = @{
Name = "$($u.FirstName) $($u.LastName)"
GivenName = $u.FirstName
Surname = $u.LastName
DisplayName = "$($u.FirstName) $($u.LastName)"
SamAccountName = $sam
UserPrincipalName = $upn
EmailAddress = $upn
Department = $u.Department
Title = $u.Title
Path = $u.OU
AccountPassword = $initialPassword
ChangePasswordAtLogon = $true # force a reset on first sign-in
Enabled = $true
WhatIf = $WhatIf
}
try {
New-ADUser @params
if (-not $WhatIf) { Write-Host "Created $sam" -ForegroundColor Green }
}
catch {
Write-Warning "FAILED to create $sam : $($_.Exception.Message)"
}
}
Two things worth understanding before you trust it:
- The password.
New-ADUser's-AccountPasswordtakes aSecureString, which is why I useRead-Host -AsSecureString— I'm not going to hand you a script that hard-codes a plaintext password into a.ps1on disk. Everyone in the batch gets the same initial password and is forced to change it at first logon via-ChangePasswordAtLogon $true. If your domain password policy rejects the string you type,New-ADUserwill throw, and thecatchblock prints why. -WhatIfis plumbed through. SplattingWhatIf = $WhatIfinto the parameter hashtable means the switch on the script controls the switch on the cmdlet. Run it with-WhatIfand nothing is written.
Run the dry run first
Always. This creates nothing and prints what it would do:
.\New-UsersFromCsv.ps1 -CsvPath 'C:\path\to\newusers.csv' -WhatIf
You'll see a What if: line per user. Confirm the names, the SamAccountNames, and especially the target OU are right. When you're satisfied, run it for real:
.\New-UsersFromCsv.ps1 -CsvPath 'C:\path\to\newusers.csv'
It will prompt once for the initial password, then create each account and print a green line per success.
Verify it worked
Pull the accounts back out of AD and confirm they landed where you meant them to. This lists everyone under the target OU with the fields you care about:
Get-ADUser -SearchBase 'OU=Staff,DC=example,DC=com' -Filter * `
-Properties Department, Title, EmailAddress |
Select-Object SamAccountName, Name, Department, Title, EmailAddress, Enabled |
Format-Table -AutoSize
Check a single account in detail:
Get-ADUser -Identity alovelace -Properties * | Format-List Name, SamAccountName, UserPrincipalName, Enabled, DistinguishedName
Confirm Enabled is True and the DistinguishedName shows the OU you expected. If you have more than one DC, remember replication isn't instant — query the DC you wrote to, or give it a minute.
Undo it if you got it wrong
Account creation is reversible: you delete the accounts. The safe pattern is to select exactly what you created, preview with -WhatIf, then remove. To pull the batch straight from your CSV rather than guessing:
# Preview the removal first - creates the same list, deletes nothing.
Import-Csv 'C:\path\to\newusers.csv' | ForEach-Object {
Remove-ADUser -Identity $_.SamAccountName.Trim() -WhatIf
}
Read that output carefully. If — and only if — it lists exactly the accounts you meant to undo, drop the -WhatIf to actually remove them. Remove-ADUser prompts for confirmation by default, which is a second safety net; keep it.
Import-Csv 'C:\path\to\newusers.csv' | ForEach-Object {
Remove-ADUser -Identity $_.SamAccountName.Trim()
}
Deleting a user is a real deletion. If your domain has the AD Recycle Bin enabled you can restore recently-deleted objects, but don't rely on that as a plan — get the dry run right instead.
Where to go from here
If you need to set attributes this script doesn't cover — manager, office, group membership, a home directory — the mainstream approach is to add columns to the CSV and either pass them to New-ADUser (for attributes it accepts directly) or follow up with Set-ADUser and Add-ADGroupMember in the same loop. Check the exact parameter names against the official docs before adding them; the module accepts a lot, but not everything by the name you'd guess. See Microsoft Learn for New-ADUser, Set-ADUser, and Get-ADUser for the authoritative parameter lists.
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
Related guides
Batch-Create Active Directory Users from CSV with PowerShell
This guide gives you a PowerShell script that reads a CSV file of new employees and creates one Active Directory user account per row, with a per-row try/catch so that one bad line doesn't halt the whole batch. Its purpose is bulk onboarding — creating dozens or hundreds of accounts without clicking through the console each time.
Bulk-Update AD User Attributes from a CSV
This guide reads a CSV of users and writes two attributes back to Active Directory for each one: Title and Department . Nothing is created or deleted — existing user objects have those two fields overwritten with the values in your file. That overwrite is a real change: if the CSV has a wrong value in a row, that user's title or department is now wrong until you fix it. There is no built-in "undo," so the safety step below is to export the current values first so you can put them back.
Update Active Directory User Details with PowerShell
This guide changes existing Active Directory user objects: it sets the email address, job title, and department on one account or a batch of accounts. It does not create or delete anything. But it overwrites whatever those attributes held before, and Active Directory keeps no built-in undo — if you set the wrong department on 200 people, the only way back is to set it again with the correct value. So treat the write as permanent unless you record the old values first (I show how below).
Automate Moving AD Users Between OUs From a CSV
This procedure reads a CSV of user accounts and their destination OUs, then moves each account to its target OU with PowerShell's Move-ADObject . Moving a user changes its distinguished name (DN). That matters because anything scoped by DN or OU — Group Policy links, delegated permissions, and OU-based filters — will start or stop applying to the account the moment it moves. The move itself does not delete the account or its group memberships, and it is reversible if you know where the account came from — which is why the script below records the original OU of every user before it touches anything.




