List all SPNs used in your Active Directory

Photo of author
Written By Jan Reilink

Windows Server systems administrator & enthusiast.

There are a lot of hints & tips out there for troubleshooting SPNs, or Service Principal Names. Listing duplicate SPNs is fairly easy, just use setspn -X on your command-line and you’ll find out. But how do you find out which SPNs are used for which users and computers are used for this?

An SPN or Service Principal Name is a unique identity for a service, mapped with a specific account (mostly service account). Using an SPN, you can create multiple aliases for a service mapped with an Active Directory domain account.

SetSPN command-line

To set, list or delete the SPN, we use an in-built command line tool SETSPN provided by Microsoft.

Quite some scripts assume you’re looking for a specific SPN (HTTP/…), a specific user, or a specific computer. For example, use setspn to find Service Principal Names (SPNs) linked to a certain computer:

setspn -L <ServerName>
Code language: PowerShell (powershell)

Or setspn to find SPNs linked to a certain user account:

setspn -L <domain\user>
Code language: PowerShell (powershell)

And now you need a general script to list all SPNs, for all users and all computers…

Nice to know fact, Service Principal Names (SPNs) are set as an attribute on the user or computer accounts. That makes it fairly ease to query for that attribute. And modern admins do PowerShell, right?

List SPNs using Powershell

So… Save the following code into a new PowerShell .ps1 file and run it in your domain. It’ll list the SPNs.

# Source / credit: # cls $search = New-Object DirectoryServices.DirectorySearcher([ADSI]"") $search.filter = "(servicePrincipalName=*)" ## You can use this to filter for OU's: ## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' } $results = $search.Findall() foreach( $result in $results ) { $userEntry = $result.GetDirectoryEntry() Write-host "Object Name = " $ -backgroundcolor "yellow" -foregroundcolor "black" Write-host "DN = " $userEntry.distinguishedName Write-host "Object Cat. = " $userEntry.objectCategory Write-host "servicePrincipalNames" $i=1 foreach( $SPN in $userEntry.servicePrincipalName ) { Write-host "SPN ${i} =$SPN" $i+=1 } Write-host "" }
Code language: PowerShell (powershell)

Or use dsquery on your CMD.exe command-line:

dsquery * "ou=domain controllers,dc=yourdomain,dc=com" -filter "(&(objectcategory=computer) (servicePrincipalName=*))" -attr distinguishedName servicePrincipalName > spns.txt
Code language: PowerShell (powershell)

This is a valuable script and information reference for your own documentation.

Did you like: List all SPNs used in your Active Directory

Then please, take a second to support Sysadmins of the North and donate!

Your generosity helps pay for the ongoing costs associated with running this website like coffee, hosting services, library mirrors, domain renewals, time for article research, and coffee, just to name a few.

10 thoughts on “List all SPNs used in your Active Directory”

  1. A few enhancement:

    class Spn {
        static [int]$counter
            $ = [Spn]::counter++
            $this.spnChain = $spnChainIs
            $temp = $spnChainIs.Split("/")
            $this.serviceClass = $temp[0]
            $ = $temp[1]
            $ = [Spn]::counter++
            $this.serviceClass = $portIs
            $ = $objectIs
            $this.spnChain = ($this.serviceClass + "/" + $
        [string] ToString(){
            return ("$($this.spnChain)")
    class Spns {
    $search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
    $search.filter = "(servicePrincipalName=*)"
    ## You can use this to filter for OU's:
    ## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' }
    $results = $search.Findall()
    $report = @()
    foreach( $result in $results ) {
    	$userEntry = $result.GetDirectoryEntry()
        [Spns]$userSPNs = [Spns]::new()
        $userSPNs.dN             = $userEntry.distinguishedName
        $           = $
        $userSPNs.objectCategory = $userEntry.objectCategory
        [Spn]::counter = 0
    	foreach( $SPN in $userEntry.servicePrincipalName ) {
            [Spn]$oneSpn = [Spn]::new($SPN)
            $userSPNs.spnss += $oneSpn #.ToString()
        $report += $userSPNs
    $report | Measure-Object
    $report | Where-Object {($_.spnss).spnChain -like "*changepw*"}
  2. if the tusk is just to list all the SPNs in your domain, why just not simply:
    Get-ADUser -filter * -prop * | where{$_.serviceprincipalname -ne $null} | select name, serviceprincipalname

  3. How can the above PowerShell script be modified to show just one server? I have tried different things but cannot get it to work.


  4. If using dsquery this filter will return user and computer objects
    -filter “(&(|(objectcategory=computer)(objectcategory=user))(servicePrincipalName=*))”

    • Thanks for your addition!

      Update, a note to “John Doe’s” -Q addition: it seems like the -Q query modifier is removed in Windows Server 2016 and up. It’s available in the help of my Windows Server 2012 R2 servers, but not in 2016:

      d:\deployment>setspn /?
      Usage: setspn [switches data] computername
        Where "computername" can be the name or domain\name
         -R = reset HOST ServicePrincipalName
          Usage:   setspn -R computername
         -A = add arbitrary SPN
          Usage:   setspn -A SPN computername
         -D = delete arbitrary SPN
          Usage:   setspn -D SPN computername
         -L = list registered SPNs
          Usage:   setspn [-L] computername
      setspn -R daserver1
         It will register SPN "HOST/daserver1" and "HOST/{DNS of daserver1}"
      setspn -A http/daserver daserver1
         It will register SPN "http/daserver" for computer "daserver1"
      setspn -D http/daserver daserver1
         It will delete SPN "http/daserver" for computer "daserver1"

Hi! Join the discussion, leave a reply!

%d bloggers like this: