SharePoint Online: Find Content Type usage using PowerShell

Requirement: Find where a Content Type is being used in SharePoint Online.

Want to get the usage information for content types in SharePoint Online? Well, In this blog post, we will show you how to find out how content types are being used in SharePoint Online using PowerShell. You may have to find the content type usage in scenarios like:

  • You are getting the “content type is still in use” error when trying to delete a content type.
  • You are trying to determine where a particular content type is used, etc.

PowerShell to Find Content Type Usage in SharePoint Online

A content type describes the metadata and behavior of items in a list or library. Unlike SharePoint On-premises, We don’t have SPContentTypeUsage class available in CSOM. So, we are left with an option: Scan each and every list to get the content type usage!

#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

#Function to get the content type usage 
Function Find-SPOContentTypeUsage([String]$SiteURL)
{
    Try{
        Write-host -f Yellow "Processing Site:" $SiteURL

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
    
        #Get All Lists of the Web
        $Ctx.Load($Ctx.Web)
        $Ctx.Load($Ctx.Web.Lists)
        $Ctx.Load($ctx.Web.Webs)
        $Ctx.ExecuteQuery()

        #Get content types of each list from the web
        $ContentTypeUsages=@()
        ForEach($List in $Ctx.Web.Lists)
        {
            $ContentTypes = $List.ContentTypes
            $Ctx.Load($ContentTypes)
            $Ctx.Load($List.RootFolder)
            $Ctx.ExecuteQuery()
            
            #Get List URL
            If($Ctx.Web.ServerRelativeUrl -ne "/")
            {
                $ListURL=  $("{0}{1}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''), $List.RootFolder.ServerRelativeUrl)
            }
            else
            {
                $ListURL=  $("{0}{1}" -f $Ctx.Web.Url, $List.RootFolder.ServerRelativeUrl)
            }
  
            #Get each content type data
            ForEach($CType in $ContentTypes)
            {
                $ContentTypeUsage = New-Object PSObject
                $ContentTypeUsage | Add-Member NoteProperty SiteURL($SiteURL)
                $ContentTypeUsage | Add-Member NoteProperty ListName($List.Title)
                $ContentTypeUsage | Add-Member NoteProperty ListURL($ListURL)
                $ContentTypeUsage | Add-Member NoteProperty ContentTypeName($CType.Name)
                $ContentTypeUsages += $ContentTypeUsage
            }
        }
        #Export the result to CSV file
        $ContentTypeUsages | Export-CSV $ReportOutput -NoTypeInformation -Append

         #Iterate through each subsite of the current web and call the function recursively
        foreach ($Subweb in $Ctx.web.Webs)
        {
            #Call the function recursively to process all subsites underneaththe current web
            Find-SPOContentTypeUsage($Subweb.url)
        }
    }
    Catch {
    write-host -f Red "Error Generating Content Type Usage Report!" $_.Exception.Message
    }
}

#Config Parameters
$SiteURL="https://crescent.sharepoint.com"
$ReportOutput ="C:\Temp\ContentTypeUsage.csv"

#Get Credentials to connect
$Cred= Get-Credential

#Delete the Output Report, if exists
if (Test-Path $ReportOutput) { Remove-Item $ReportOutput }

#Call the function to get the content type usage
Find-SPOContentTypeUsage $SiteURL

Here is the sample output of the script.

This PowerShell script gets all content types of all lists and libraries in a SharePoint Online site collection. What if you want to find where a specific content type is used?

SharePoint Online: Find Where a Specific Content Type is used using PowerShell

Now, let’s find all documents with a content type in SharePoint Online using PowerShell. Here is how to get content type usage in SharePoint Online.

#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

#Function to get a particular content type usage
Function Get-SPOContentTypeUsage([String]$SiteURL, [String]$ContentTypeName)
{
    Try{
        Write-host -f Yellow "Processing Site:" $SiteURL

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
    
        #Get All Lists of the Web
        $Ctx.Load($Ctx.Web)
        $Ctx.Load($Ctx.Web.Lists)
        $Ctx.Load($ctx.Web.Webs)
        $Ctx.ExecuteQuery()

        #Get content types of each list from the web
        $ContentTypeUsages=@()
        ForEach($List in $Ctx.Web.Lists)
        {
            $ContentTypes = $List.ContentTypes
            $Ctx.Load($ContentTypes)
            $Ctx.Load($List.RootFolder)
            $Ctx.ExecuteQuery()
            
            #Get List URL
            If($Ctx.Web.ServerRelativeUrl -ne "/")
            {
                $ListURL=  $("{0}{1}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''), $List.RootFolder.ServerRelativeUrl)
            }
            else
            {
                $ListURL=  $("{0}{1}" -f $Ctx.Web.Url, $List.RootFolder.ServerRelativeUrl)
            }
  
            #Get each content type data
            ForEach($CType in $ContentTypes)
            {
                If($CType.Name -eq $ContentTypeName)
                {
                    $ContentTypeUsage = New-Object PSObject
                    $ContentTypeUsage | Add-Member NoteProperty SiteURL($SiteURL)
                    $ContentTypeUsage | Add-Member NoteProperty ListName($List.Title)
                    $ContentTypeUsage | Add-Member NoteProperty ListURL($ListURL)
                    $ContentTypeUsage | Add-Member NoteProperty ContentTypeName($CType.Name)
                    $ContentTypeUsages += $ContentTypeUsage
                    Write-host -f Green "Found the Content Type at:" $ListURL
                }
            }
        }
        #Export the result to CSV file
        $ContentTypeUsages | Export-CSV $ReportOutput -NoTypeInformation -Append

         #Iterate through each subsite of the current web and call the function recursively
        foreach ($Subweb in $Ctx.web.Webs)
        {
            #Call the function recursively to process all subsites underneaththe current web
            Get-SPOContentTypeUsage $Subweb.url $ContentTypeName
        }
    }
    Catch {
    write-host -f Red "Error Generating Content Type Usage Report!" $_.Exception.Message
    }
}

#Config Parameters
$SiteURL="https://crescent.sharepoint.com"
$ReportOutput ="C:\Temp\ContentTypeUsage.csv"
$ContentTypeName="Business Contacts"

#Get Credentials to connect
$Cred= Get-Credential

#Delete the Output Report, if exists
if (Test-Path $ReportOutput) { Remove-Item $ReportOutput }

#Call the function to get the content type usage
Get-SPOContentTypeUsage $SiteURL $ContentTypeName 

This PowerShell finds files with content types in SharePoint Online, and it also gets you all locations of the specific content type usage.

PnP PowerShell to Get Content Type Usage in SharePoint Online Site

#Parameters
$SiteURL="https://crescent.sharepoint.com/sites/PMO"
$ReportOutput ="C:\Temp\ContentTypeUsage.csv"
$ContentTypeName="Crescent Project V2"

#Delete the Output Report, if exists
If (Test-Path $ReportOutput) { Remove-Item $ReportOutput }

Try{
    #Connect to the Site        
    Connect-PnPOnline -Url $SiteURL -Interactive

    #Get All Lists
    $Lists = Get-PnPList -Includes RootFolder | Where-Object {$_.Hidden -eq $False}
    
    #Get content types of each list from the web
    $ContentTypeUsages=@()
    ForEach($List in $Lists)
    {
        Write-host -f Yellow "Scanning List:" $List.Title
        $ListURL =  $List.RootFolder.ServerRelativeUrl

        #get all content types from the list
        $ContentType = Get-PnPContentType -List $List | Where {$_.Name -eq $ContentTypeName}
  
        #Collect list details
        If($ContentType)
        {
            $ContentTypeUsage = New-Object PSObject
            $ContentTypeUsage | Add-Member NoteProperty SiteURL($SiteURL)
            $ContentTypeUsage | Add-Member NoteProperty ListName($List.Title)
            $ContentTypeUsage | Add-Member NoteProperty ListURL($ListURL)
            $ContentTypeUsage | Add-Member NoteProperty ContentTypeName($ContentType.Name)
            Write-host -f Green "`tFound the Content Type in Use!" 

            #Export the result to CSV file
            $ContentTypeUsage | Export-CSV $ReportOutput -NoTypeInformation -Append
        }
    }
}
Catch {
    write-host -f Red "Error Generating Content Type Usage Report!" $_.Exception.Message
}

Please note that you cannot delete a content type as long as the content type is in use on any SharePoint sites. Also, To remove a content type from the SharePoint site, any item that uses the particular content type must either change its content type or completely be removed (even from the 1st stage & 2nd stage recycle bins).

Here is another post to find where a content type is used in SharePoint On-premises: Find Content Type Usage in SharePoint using PowerShell

Salaudeen Rajack

Salaudeen Rajack - SharePoint Expert with Two decades of SharePoint Experience. Love to Share my knowledge and experience with the SharePoint community, through real-time articles!

5 thoughts on “SharePoint Online: Find Content Type usage using PowerShell

  • Hi Salaudeen,

    Thank you for the response, not sure if I’ve misunderstood something though. The issue is with 2 content types in a site that is not itself a Hub site; but yet I can’t delete the two content types because SPO claims they are in use somewhere. It’s my understanding that content types can only be shared down (i.e. from Hub site to sub sites) but not up nor across?

    I suspect this is one I need to take up with MS support (yay me)…

    Reply
  • Hi Salaudeen,

    I’m attempting to use your solutions, but I’m getting the following error at runtime,
    Error Generating Content Type Usage Report! Exception calling “ExecuteQuery” with “0” argument(s): “The sign-in name or password does not match one in the Microsoft account system.”

    I rather suspect it’s due to MFA, and I’m trying to fathom how I replace your connection method with:
    connect-pnponline -url “target” -interactive

    Any advise?

    Reply
    • Sounds like your account is MFA enabled! PnP PowerShell supports MFA-enabled accounts natively. I’ve added the PnP script to the article.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *