SharePoint Online: Change Content Type of List Items using PowerShell

Requirement: Change the Content Types of All Items in a SharePoint Online List.

How to Change the Content Type of existing Items in SharePoint Online?

In SharePoint Online, content types are used to define the metadata and behavior of items in lists and libraries. Occasionally, you may need to change the content type of existing items in a list or library to improve them and adhere to business requirements. This guide will show you how to make the switch using the web browser interface easily, and I’ll show you how to use PowerShell to change the content type!

You can change the content type of existing list items by editing the particular item and switching the “Content Type” field.

sharepoint online change content type powershell

Well, let’s bulk change the content type in SharePoint Online with PowerShell.

Before changing the content type of list items, You must add the content type to the list first: How to Add a Content Type to List in SharePoint Online using PowerShell?

Change Content type in SharePoint Online using PowerShell:

Let us change the content type “Crescent Project V1” with “Crescent Project V2” for all list items (whichever item uses the content type “Crescent Project V1”).

#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 Change the Content Type of All Items in SharePoint Online list using powershell
Function Change-SPOContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ListName = $(throw "Enter the List Name!"),
        [string]$OldContentTypeName = $(throw "Enter the Old Content Type Name!"),
        [string]$NewContentTypeName = $(throw "Enter the New Content Type Name!")
    )
    Try {
        #Get Credentials to connect
        $Cred= Get-Credential
 
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Get the Web
        $Web = $Ctx.Web
        $Ctx.Load($Web)
        $Ctx.ExecuteQuery()
        
        #Get the List & and content types
        $List = $Web.lists.GetByTitle($ListName)
        $ContentTypes = $List.ContentTypes
        $Ctx.Load($List)
        $Ctx.Load($ContentTypes)
        $Ctx.ExecuteQuery()

        #Get the content type to Update
        $OldContentType = $ContentTypes | Where {$_.Name -eq $OldContentTypeName}
        $NewContentType = $ContentTypes | Where {$_.Name -eq $NewContentTypeName}

        If($NewContentType -eq $Null)
        {
            Write-Host "Content Type '$NewContentTypeName' doesn't Exist in the list. Add the Content Type to the List First!" -ForegroundColor Yellow
            Return
        }

        #Define Query to get List Items in batch
        $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
        $Query.ViewXml = "@
        <View Scope='RecursiveAll'>
            <Query>
                <OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
            </Query>
            <RowLimit Paged='TRUE'>$BatchSize</RowLimit>
        </View>
        @"

        $Counter = 1
        $BatchCounter = 0
        #Get List Items in Batch
        Do
        {
            $ListItems = $List.GetItems($Query)
            $Ctx.Load($ListItems)
            $Ctx.ExecuteQuery()
            $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition
            $Ctx.ExecuteQuery()
            $BatchCounter += $ListItems.Count

            #Get All List Items with Old Content Type
            $ItemsToUpdate = $ListItems | Where {$_["ContentTypeId"].StringValue -eq ($OldContentType.ID)}
            Write-host "Number of Items Found with Old Content Type in the Batch ($Counter to $BatchCounter):" $ItemsToUpdate.count
            $Counter = $BatchCounter

            If($ItemsToUpdate.count -gt 0)
            {
                #Iterate through each item with old content type and update the conent type
                ForEach($Item in $ItemsToUpdate)
                {
                    $Item["ContentTypeId"]  = $NewContentType.Id
                    $Item.Update()
                    Write-host "Content Type Update Quued for List Item ID: $($Item.ID)" -ForegroundColor yellow
                }
                $Ctx.ExecuteQuery()
                write-host "Content Types Updated Successfully!" -ForegroundColor  Green
            }
        }While($Query.ListItemCollectionPosition -ne $null)
    }
    Catch {
        write-host -f Red "Error Changing Content Type!" $_.Exception.Message
    }
}

#Variables
#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/pmo"
$ListName ="Projects"
$OldContentTypeName= "Crescent Project V1"
$NewContentTypeName= "Crescent Project V2"
$BatchSize = 500

#Call the function to Change the content type
Change-SPOContentType -SiteURL $SiteURL -ListName $ListName -OldContentTypeName $OldContentTypeName -NewContentTypeName $NewContentTypeName 

This PowerShell changes the content type programmatically for all items in the SharePoint Online list. This can be useful if you need to change the content type of files already in your SharePoint site.

SharePoint Online: Change Content Type using PnP PowerShell

Here is how to change content type in SharePoint Online with the PnP PowerShell Module’s Set-PnPListItem cmdlet:

#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/projects"
$ListName = "Project Proposal"
$OldContentTypeName = "Crescent Proposal V1"
$NewContentTypeName = "Crescent Project Proposal V2"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive

#Get the New Content Type from the List
$NewContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $NewContentTypeName}

#Get List Items of Old content Type
$ListItems = Get-PnPListItem -List $ListName -Query "<View><Query><Where><Eq><FieldRef Name='ContentType'/><Value Type='Computed'>$OldContentTypeName</Value></Eq></Where></Query></View>"
Write-host "Total Number of Items with Old Content Type:"$ListItems.count

ForEach($Item in $ListItems)
{
    #Change the Content Type of the List Item
    Set-PnPListItem -List $ListName -Identity $Item -ContentType $NewContentType
}

While the above script works perfectly fine for lists and libraries with less than 5000 items, the “PageSize” parameter has no effect when combined with the “Query” parameter of Get-PnPListItem cmdlet and gets “Get-PnPListItem : The attempted operation is prohibited because it exceeds the list view threshold.” error. So, Here is the PowerShell script to handle larger lists:

Let me show you how to use PnP PowerShell to change the content type of list items in SharePoint Online:

#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/projects"
$ListName = "Project Proposal"
$OldContentTypeName = "Crescent Proposal V1"
$NewContentTypeName = "Crescent Project Proposal V2"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$List =  Get-PnPList -Identity $ListName

#Get the Old and New Content Types from the List
$OldContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $OldContentTypeName}
$NewContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $NewContentTypeName}

#Get List Items of old content type from the list
$global:counter = 0;
$ListItems = Get-PnPListItem -List $List -PageSize 500 -Fields ContentTypeId -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete `
              ($global:Counter / ($List.ItemCount) * 100) -Activity "Getting Items from List" -Status "Checking Items $global:Counter to $($List.ItemCount)"} | Where {$_.FieldValues.ContentTypeId.ToString() -eq $OldContentType.StringId}

Write-host "Total Number of Items with Old Content Type Found:"$ListItems.count
#Loop through List Items
ForEach($Item in $ListItems)
{
    #Change the Content Type of the List Item
    Set-PnPListItem -List $ListName -Identity $Item -ContentType $NewContentType | Out-Null
    Write-host "Content Type Updated for List Item ID $($Item.ID)!" -f Green
}

Once you execute this script, all the items in the list will update their content type to the new one. By following these simple steps, you can easily update the content types of items in your lists and libraries, improving your SharePoint management skills and streamlining your workflow.

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

7 thoughts on “SharePoint Online: Change Content Type of List Items using PowerShell

  • This was amazing. Thank you SO MUCH for sharing!!

    Reply
  • I only get errors running either of the bottom two scripts, any idea how i can get it to work or what i am doing wrong ?

    Get-PnPList:
    Line |
    7 | $List = Get-PnPList -Identity $ListName
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | The remote server returned an error: (404) Not Found.
    Get-PnPContentType:
    Line |
    10 | $OldContentType = Get-PnPContentType -List $ListName | Where {$_.Name …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | The remote server returned an error: (404) Not Found.
    Get-PnPContentType:
    Line |
    11 | $NewContentType = Get-PnPContentType -List $ListName | Where {$_.Name …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | The remote server returned an error: (404) Not Found.
    Get-PnPListItem:
    Line |
    15 | $ListItems = Get-PnPListItem -List $List -PageSize 500 -Fields Conten …
    | ~~~~~
    | Cannot bind argument to parameter ‘List’ because it is null.

    Reply
  • Is it possible to do this without updating modified by of the items?

    Reply
  • If my list is having more than 5000 items the query is throwing list item threshold and not able to get items. How to make this above script to work for list with more than 5000 items.

    Reply
    • I’m having the same question how to get it working with more than 5000 items?

      Reply
      • Post updated with the CSOM & PnP PowerShell scripts to handle larger lists and Libraries.

        Reply
      • Thank you for the updated version, works like a charm now 🙂

        Reply

Leave a Reply

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