SharePoint Online: Export-Import Content Type using PowerShell

Requirement: Export-Import Content Types in SharePoint Online using PowerShell.

Export Content Type in SharePoint Online using PowerShell

Are you looking to export or import content types in SharePoint Online? If so, PowerShell is here to help! This blog post will show you how to export and import content types between SharePoint Online sites using PowerShell. This can be useful if you want to copy content types from one site to another or if you want to move content types between development and production environments.

#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 Export the Content Type in SharePoint Online using powershell
Function Export-SPOContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ContentTypeName = $(throw "Enter the Content Type Name!"),
        [string]$ExportFile = $(throw "Enter the File to Export!")
    )
    Try {
        #Get Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
 
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Credentials
        
        #Get the Web
        $Web = $Ctx.Web
        $Ctx.Load($Web)
        $Ctx.ExecuteQuery()
        
        #Get Content Types from the Web
        $ContentTypes = $Web.ContentTypes
        $Ctx.Load($ContentTypes)
        $Ctx.ExecuteQuery()

        #Get the content type to Export
        $ContentType = $ContentTypes | Where {$_.Name -eq $ContentTypeName}

        If($ContentType -ne $Null)
        {
            #Create Export XML File and export the schema of the content type
            New-Item $ExportFile -type file -force | Out-Null

            #sharepoint online powershell export content type
            Add-Content $ExportFile "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
            Add-Content $ExportFile $ContentType.SchemaXml
 
            write-host "Content Type '$ContentTypeName' Exported Successfully!" -ForegroundColor  Green
        }
        else
        {            
            Write-Host "Content Type '$ContentTypeName' Doesn't Exist in the Site!" -ForegroundColor Yellow
        }
    }
    Catch {
        write-host -f Red "Error Exporting Content Type!" $_.Exception.Message
    }
}

#Variables
$SiteURL = "https://Crescent.sharepoint.com/"
$ContentTypeName= "Crescent Project V1"
$ExportFile = "C:\Temp\CrescentProjV1.xml"

#Call the function to Export the content type
Export-SPOContentType -SiteURL $SiteURL -ContentTypeName $ContentTypeName -ExportFile $ExportFile

And the script outputs an XML:

powershell to export import content type sharepoint online

We can also export the content type with PnP PowerShell as:

#Function to Export the Content Type in SharePoint Online using powershell
Function Export-PnPContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ContentTypeName = $(throw "Enter the Content Type Name!"),
        [string]$ExportFile = $(throw "Enter the File to Export!")
    )
    Try {
        #Connect to SharePoint Online
        Connect-PnPOnline -Url $SiteURL -Interactive

        #Get the content type to Export
        $ContentType = Get-PnPContentType -Identity $ContentTypeName -ErrorAction SilentlyContinue
 
        If($ContentType -ne $Null)
        {
            #Create Export XML File and export the schema of the content type
            New-Item $ExportFile -type file -force | Out-Null
 
            #sharepoint online powershell export content type
            Add-Content $ExportFile "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
            Add-Content $ExportFile $ContentType.SchemaXml
  
            write-host "Content Type '$ContentTypeName' Exported Successfully!" -ForegroundColor  Green
        }
        else
        {            
            Write-Host "Content Type '$ContentTypeName' doesn't Exist in the Site!" -ForegroundColor Yellow
        }
    }
    Catch {
        write-host -f Red "Error Exporting Content Type!" $_.Exception.Message
    }
}
 
#Variables
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$ContentTypeName= "Crescent Announcement"
$ExportFile = "C:\Temp\CrescentAnn.xml"

#Call the function to Export the content type
Export-PnPContentType -SiteURL $SiteURL -ContentTypeName $ContentTypeName -ExportFile $ExportFile

PowerShell to Import a Content Type from XML in SharePoint Online

The next step is restoring the exported content type to wherever required.

#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 Import the Content Type in SharePoint Online using powershell
Function Import-SPOContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ContentTypeName = $(throw "Enter the Content Type Name!"),
        [string]$ImportFile = $(throw "Enter the File to Import!")
    )
    Try {
        #Get Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
 
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Credentials
        
        #Get the Web & site columns
        $Web = $Ctx.Web
        $Ctx.Load($Web)
        $Ctx.Load($Web.Fields)
        $Ctx.ExecuteQuery()
        
        #Get existing Content Types from the Web
        $ContentTypes = $Web.ContentTypes
        $Ctx.Load($ContentTypes)
        $Ctx.ExecuteQuery()

        #Check if the content type exists already
        $ContentType = $ContentTypes | Where {$_.Name -eq $ContentTypeName}

        If($ContentType -eq $Null)
        {
            #Import the XML File
            $ContentTypeXML = [xml](Get-Content($ImportFile))

            #Create the content type
            $CTypeCreationInfo=New-Object Microsoft.SharePoint.Client.ContentTypeCreationInformation
            $CTypeCreationInfo.Name = $ContentTypeName
            $CTypeCreationInfo.Description = $ContentTypeXML.ContentType.Description
            $CTypeCreationInfo.Group = $ContentTypeXML.ContentType.Group
            $ContentType=$ContentTypes.Add($CTypeCreationInfo)
            $Ctx.ExecuteQuery()
            
            Write-host "Content Type '$ContentTypeName' Created Successfully!" -ForegroundColor Green

            Write-host "Adding Fields to the Content Type..." -ForegroundColor Yellow
            #Remove the "Version" Attribute from the XML
            $ContentTypeXML.ContentType.Fields.Field.RemoveAttribute("Version")
            
            #Add Fields to content type
            ForEach($Field in $ContentTypeXML.ContentType.Fields.Field)
            {
                #Get existing fields from content type
                $Ctx.Load($ContentType.Fields)
                $Ctx.ExecuteQuery()
                
                #Check if the content type has the field already!
                $ContentTypeField = $ContentType.Fields | Where {$_.InternalName -eq $Field.Name}
                If($ContentTypeField -eq $Null)
                {
                    #Get the site column
                    $SiteColumn = $Web.Fields | Where {$_.InternalName -eq $Field.Name}
                    If($SiteColumn -eq $Null)
                    {
                        #Add Site column to Web
                        $SiteColumn = $Web.Fields.AddFieldAsXml($Field.OuterXml, $True,[Microsoft.SharePoint.Client.AddFieldOptions]::AddFieldInternalNameHint)
                        $Ctx.ExecuteQuery()
                        Write-host "Site Column Added:" $($Field.Name)
                    }
                    Else
                    {
                        Write-host -f Yellow "Site Column '$($Field.Name)' Already Exists.. Skipping Creating site column"
                    } 
                    #Reload Web.Fields
                    $Ctx.Load($Web.Fields)
                    $Ctx.ExecuteQuery()

                    $SiteColumn = $Web.Fields | Where {$_.InternalName -eq $Field.Name}
                    #Add field to content type
                    $FieldLink = New-Object Microsoft.SharePoint.Client.FieldLinkCreationInformation
                    $FieldLink.Field = $SiteColumn
                    [Void]$ContentType.FieldLinks.Add($FieldLink)
                    $ContentType.Update($True)
                    $Ctx.ExecuteQuery() 

                    Write-host "Field $($Field.Name) Added to Content Type" -Foregroundcolor Green
                }
            } 
            write-host "Content Type '$ContentTypeName' Imported Successfully!" -ForegroundColor  Green
        }
        else
        {            
            Write-Host "Content Type '$ContentTypeName' Already Exist in the Site!" -ForegroundColor Yellow
        }
    }
    Catch {
        write-host -f Red "Error Importing Content Type!" $_.Exception.Message
    } 
}

#Variables
$SiteURL = "https://Crescent.sharepoint.com/Sites/Marketing"
$ContentTypeName= "Crescent Project V1"
$ImportFile = "C:\Temp\CrescentProjV1.xml"

#Call the function to Import the content type
Import-SPOContentType -SiteURL $SiteURL -ContentTypeName $ContentTypeName -ImportFile $ImportFile

The PnP PowerShell of the above script to restore the content type from the XML file:

#Function to Import the Content Type in SharePoint Online using powershell
Function Import-PnPContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ContentTypeName = $(throw "Enter the Content Type Name!"),
        [string]$ImportFile = $(throw "Enter the File to Import!")
    )
    Try {
        #Connect to SharePoint Online
        Connect-PnPOnline -Url $SiteURL -Interactive

        #Check if the content type to exists already
        $ContentType = Get-PnPContentType -Identity $ContentTypeName -ErrorAction SilentlyContinue
        
        If($ContentType -eq $Null)
        {
            #Import the XML File
            $ContentTypeXML = [xml](Get-Content($ImportFile))

            #Create the content type
            $ContentType = Add-PnPContentType -Name $ContentTypeName -Description $ContentTypeXML.ContentType.Description -Group $ContentTypeXML.ContentType.Group            
            Write-host "Content Type '$ContentTypeName' Created Successfully!" -ForegroundColor Green

            Write-host "Adding Fields to the Content Type..." -ForegroundColor Yellow
            #Remove the "Version" Attribute from the XML
            $ContentTypeXML.ContentType.Fields.Field.RemoveAttribute("Version")
            
            #Add Fields to content type
            ForEach($Field in $ContentTypeXML.ContentType.Fields.Field)
            {
                #Get existing fields from content type
                $ContentTypeFields = Get-PnPProperty -ClientObject $ContentType -Property Fields
                
                #Check if the content type has the field already!
                $ContentTypeField = $ContentTypeFields | Where {$_.InternalName -eq $Field.Name}
                If($ContentTypeField -eq $Null)
                {
                    #Get the site column
                    $SiteColumn = Get-PnPField | Where {$_.InternalName -eq $Field.Name}
                    If($SiteColumn -eq $Null)
                    {
                        #Add Site column to Web
                        Add-PnPFieldFromXml -FieldXml $Field.OuterXml 
                        Write-host "Site Column Added:" $($Field.Name)
                    }
                    Else
                    {
                        Write-host -f Yellow "`tSite Column '$($Field.Name)' Already Exists.. Skipping Creating site column"
                    } 

                    #get the field to add to content type
                    $SiteColumn = Get-PnPField | Where {$_.InternalName -eq $Field.Name}
                    #Add Field to Content type
                    Add-PnPFieldToContentType -Field $SiteColumn -ContentType $ContentTypeName

                    Write-host "`tField '$($Field.Name)' Added to Content Type" -Foregroundcolor Green
                }
            } 
            write-host "Content Type '$ContentTypeName' Imported Successfully!" -ForegroundColor  Green
        }
        else
        {            
            Write-Host "Content Type '$ContentTypeName' Already Exist in the Site!" -ForegroundColor Yellow
        }
    }
    Catch {
        write-host -f Red "Error Importing Content Type!" $_.Exception.Message
    } 
}

#Variables
$SiteURL = "https://crescent.sharepoint.com/sites/Operations"
$ContentTypeName= "Crescent Announcements
$ImportFile = "C:\Temp\CrescentAnn.xml"

#Call the function to Import the content type
Import-PnPContentType -SiteURL $SiteURL -ContentTypeName $ContentTypeName -ImportFile $ImportFile

When you want to re-use a content type in different site SharePoint Online site collections, without a content type hub, You can copy-paste them using this PowerShell script.

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!

8 thoughts on “SharePoint Online: Export-Import Content Type using PowerShell

  • I managed to set the parent to Document.
    #Import the XML File
    $ContentTypeXML = [xml](Get-Content($ImportFile))
    $ParentContentTypeName =”Document”
    $ParentContentType = Get-PnPContentType -Identity $ParentContentTypeName
    #Create the content type
    $ContentType = Add-PnPContentType -Name $ContentTypeName -Description $ContentTypeXML.ContentType.Description -Group $ContentTypeXML.ContentType.Group -ParentContentType $ParentContentType

    Reply
  • I have used the PnP example. My Imported content type parent is Item and not Document. How do I make sure that the parent is correct?

    Reply
  • Hello,

    how can i overwrite an existing content type , i am hiding my “TITLE” via “allow Content Management” and i want to copy over the “changes”

    Reply
  • Line 47: $ContentType=$ContentTypes.Add($CTypeCreationInfo)

    Is crashing for me with the following error message
    Error Importing Content Type! Cannot convert argument “parameters”, with value: “Microsoft.SharePoint.Client.ContentTypeCreationInformation”, for “Add” to type “Microsoft.SharePoint.Client.Co
    ntentTypeCreationInformation”: “Cannot convert the “Microsoft.SharePoint.Client.ContentTypeCreationInformation” value of type “Microsoft.SharePoint.Client.ContentTypeCreationInformation” to t
    ype “Microsoft.SharePoint.Client.ContentTypeCreationInformation”.”

    Reply
  • Anyone able to get this working with a site that has MFA on it.

    I’ve tried with something like this:
    #Connect to SharePoint
    Connect-PnPOnline -Url $SiteURL -Interactive

    #Setup the context
    $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)

    #Get the Web
    $Web = $Ctx.Web
    $Ctx.Load($Web)
    $Ctx.ExecuteQuery()

    But it always crashes at the $Ctx.ExecuteQuery() step because the the $Ctx.Web doesn’t contain any value

    Reply
    • The article is updated with the PnP PowerShell script! You can use MFA enabled accounts now.

      Reply
    • If you want to get the context from PnP PowerShell, use:

      #Connect to SharePoint
      Connect-PnPOnline -Url $SiteURL -Interactive
      
      #Get the context
      $Ctx = Get-PnPContext
      
      Reply

Leave a Reply

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