How to Download a Folder from SharePoint Online using PowerShell?

Requirement: Download a Folder from SharePoint Online.

How to Download a Folder from SharePoint Online?

Are you wondering how to download a folder from SharePoint Online? Well, this post will show you how! In just a few easy steps, you can have the contents of a SharePoint folder on your computer. In this blog post, we will show you how to download a folder (and download files in it!) from SharePoint Online.

Assuming you have read permissions at least, follow these steps to download a folder from SharePoint Online:

  1. Login to your SharePoint Online Site collection, and Navigate to the SharePoint document library or the parent folder where the Folder you want to download exists.
  2. Right-click on the Folder  >> Choose “Download” from the context menu. You can also use the “Download” button from the toolbar.
  3. This brings you a Zip file with the Selected folder and its Sub-Folders and its files.
    powershell download folder from sharepoint online

Simple, huh? You can now finally get your hands on all of those documents right in front of you without having to open another tab on your browser. Let’s see how to download a SharePoint Online folder using PowerShell.

SharePoint Online: Download Folder using PowerShell

Now, when we need to download a folder repeatedly or automatically on a scheduled basis, we can utilize PowerShell. Here is my PowerShell to download a folder from 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 Download-SPOFolder()
{ 
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [Microsoft.SharePoint.Client.Folder] $SourceFolder,
        [Parameter(Mandatory=$true)] [string] $TargetFolder
    )
    Try {
         
        #Create Local Folder, if it doesn't exist
        $FolderName = ($SourceFolder.ServerRelativeURL) -replace "/","\"
        $LocalFolder = $TargetFolder + $FolderName
        If (!(Test-Path -Path $LocalFolder)) {
                New-Item -ItemType Directory -Path $LocalFolder | Out-Null
        }
         
        #Get all Files from the folder
        $FilesColl = $SourceFolder.Files
        $Ctx.Load($FilesColl)
        $Ctx.ExecuteQuery()
 
        #Iterate through each file and download
        Foreach($File in $FilesColl)
        {
            $TargetFile = $LocalFolder+"\"+$File.Name
            #Download the file
            $FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx,$File.ServerRelativeURL)
            $WriteStream = [System.IO.File]::Open($TargetFile,[System.IO.FileMode]::Create)
            $FileInfo.Stream.CopyTo($WriteStream)
            $WriteStream.Close()
            write-host -f Green "Downloaded File:"$TargetFile
        }
         
        #Process Sub Folders
        $SubFolders = $SourceFolder.Folders
        $Ctx.Load($SubFolders)
        $Ctx.ExecuteQuery()
        Foreach($Folder in $SubFolders)
        {
            If($Folder.Name -ne "Forms")
            {
                #Call the function recursively
                Download-SPOFolder -SiteURL $SiteURL -SourceFolder $Folder -TargetFolder $TargetFolder
            }
        }
     }
    Catch {
        write-host -foregroundcolor Red "Error Downloading Folder!" $_.Exception.Message
    }
}
 
#Set parameter values
$SiteURL="https://crescent.sharepoint.com"
$FolderRelativeUrl ="Shared Documents/Reports"
$TargetFolder="C:\Docs"
 
#Setup 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()
$Web.ServerRelativeUrl+$FolderRelativeUrl
      
#Get the Folder
$SourceFolder = $Web.GetFolderByServerRelativeUrl($Web.ServerRelativeUrl+$FolderRelativeUrl)
$Ctx.Load($SourceFolder)
$Ctx.ExecuteQuery()

#Call the function to download a Folder
Download-SPOFolder -SiteURL $SiteURL -SourceFolder $SourceFolder -TargetFolder $TargetFolder 

PnP PowerShell to Download a Folder from SharePoint Online

How do I download a folder from SharePoint using PowerShell? Well, this PnP PowerShell script uses Get-PnPFolder and Get-PnPFile cmdlets to download all files and sub-folders from the specific Folder in the SharePoint Online document library to a local directory.

#Function to Download All Files from a SharePoint Online Folder - Recursively  
Function Download-SPOFolder([Microsoft.SharePoint.Client.Folder]$Folder, $DestinationFolder)
{  
    #Get the Folder's Site Relative URL
    $FolderURL = $Folder.ServerRelativeUrl.Substring($Folder.Context.Web.ServerRelativeUrl.Length)
    $LocalFolder = $DestinationFolder + ($FolderURL -replace "/","\")
    
    #Create Local Folder, if it doesn't exist
    If (!(Test-Path -Path $LocalFolder)) {
            New-Item -ItemType Directory -Path $LocalFolder | Out-Null
            Write-host -f Yellow "Created a New Folder '$LocalFolder'"
    }
           
    #Get all Files from the folder
    $FilesColl = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderURL -ItemType File 
    #Iterate through each file and download Sourcefile
    Foreach($File in $FilesColl)
    {
        Get-PnPFile -ServerRelativeUrl $File.ServerRelativeUrl -Path $LocalFolder -FileName $File.Name -AsFile -force
        Write-host -f Green "`tDownloaded File from '$($File.ServerRelativeUrl)'"
    }
    
    #Get Subfolders of the Folder and call the function recursively
    $SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderURL -ItemType Folder
    Foreach ($Folder in $SubFolders | Where {$_.Name -ne "Forms"})
    {
        Download-SPOFolder $Folder $DestinationFolder
    }
}  

#Set Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$FolderSiteRelativeURL = "/Team Documents/2018"
$DownloadPath ="C:\Docs" #TargetFilePath
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
 
#Get the folder to download
$Folder = Get-PnPFolder -Url $FolderSiteRelativeURL
 
#Call the function to download all files from a folder
Download-SPOFolder $Folder $DownloadPath

Download a Folder with its Subfolders and Files from a Larger Document Libraries

While the above scripts work perfectly fine, We may encounter Listview threshold exceeded issues on larger libraries. To mitigate that issue, Here is my alternate script that downloads files from a SharePoint Online folder to the local disk:

#Set Parameters
$SiteURL = "https://Crescent.sharepoint.com/sites/marketing"
$FolderServerRelativeURL = "/Sites/Marketing/Shared Documents/New"
$DownloadPath ="C:\Docs\New"
  
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$Web = Get-PnPWeb

#Get the Folder to download
$Folder = Get-PnPFolder -Url $FolderServerRelativeURL -Includes ListItemAllFields.ParentList
#Get the Folder's Site Relative URL
$FolderSiteRelativeURL = $FolderServerRelativeUrl.Substring($Web.ServerRelativeUrl.Length)

$List = $Folder.ListItemAllFields.ParentList
#Get all Folders from List - with progress bar
$global:counter = 0;
$ListItems = Get-PnPListItem -List $List -PageSize 500 -Fields FileLeafRef -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete `
                ($global:Counter / ($List.ItemCount) * 100) -Activity "Getting Items from List:" -Status "Processing Items $global:Counter to $($List.ItemCount)";} | Where {$_.FieldValues.FileRef -like "$($FolderServerRelativeUrl)*"} 
Write-Progress -Activity "Completed Retrieving Items from Folder $FolderServerRelativeURL" -Completed

#Get Subfolders of the Folder
$SubFolders = $ListItems | Where {$_.FileSystemObjectType -eq "Folder" -and $_.FieldValues.FileLeafRef -ne "Forms"}
$SubFolders | ForEach-Object {
    #Ensure All Folders in the Local Path
    $LocalFolder = $DownloadPath + ($_.FieldValues.FileRef.Substring($Web.ServerRelativeUrl.Length)) -replace "/","\"
    #Create Local Folder, if it doesn't exist
    If (!(Test-Path -Path $LocalFolder)) {
            New-Item -ItemType Directory -Path $LocalFolder | Out-Null
    }
    Write-host -f Yellow "Ensured Folder '$LocalFolder'"
}
#Get all Files from the folder
$FilesColl =  $ListItems | Where {$_.FileSystemObjectType -eq "File"}
#Iterate through each file and download
$FilesColl | ForEach-Object {
    $FileDownloadPath = ($DownloadPath + ($_.FieldValues.FileRef.Substring($Web.ServerRelativeUrl.Length)) -replace "/","\").Replace($_.FieldValues.FileLeafRef,'')
    Get-PnPFile -ServerRelativeUrl $_.FieldValues.FileRef -Path $FileDownloadPath -FileName $_.FieldValues.FileLeafRef -AsFile -force
    Write-host -f Green "Downloaded File from '$($_.FieldValues.FileRef)'"
}

To download all files and folders from a SharePoint Online document library, use: PowerShell to download all files from SharePoint Online Library

How do I download a file from SharePoint using PnP PowerShell?

To download a file from SharePoint using PnP PowerShell, connect to your SharePoint Online site using the Connect-PnPOnline cmdlet first. Then use the PnP PowerShell cmdlet “Get-PnPFile” to download a file from SharePoint Online. For example, the following PowerShell script downloads a file named “Document.docx” from a SharePoint Online site and saves it to the C:\Temp folder: Get-PnPFile -Url “/sites/yoursite/Shared Documents/Document.docx” -Path “C:\Temp” -FileName “Document.docx”
More info: PowerShell to download a file from SharePoint Online

How do I upload files and folders to SharePoint Online?

To upload files and folders to SharePoint Online, follow these steps: Navigate to the SharePoint Online document library where you want to upload the folders. Click on the Upload button from the toolbar and Select the Folder option. Browse to the location of the folder that you want to upload, Select the Folder and click on the “Upload” button. Alternatively, you can use PowerShell to upload a folder along with its files: Upload folder to SharePoint Online using PowerShell

How do I share a folder with someone outside an organization in SharePoint?

To share a folder with someone outside your organization in SharePoint Online, you must first ensure external sharing is enabled for your domain and site. Once confirmed, you can grant them access to the specific folder by selecting it, clicking “Share”, and entering their email address. You can also choose to set specific permissions for the folder, such as read-only or edit access. More here: How to share a folder on SharePoint with external users?

How do I sync a SharePoint folder to a local drive?

To sync a SharePoint folder to a local drive, use the OneDrive sync client. First, make sure you have the OneDrive app installed on your computer. Then, navigate to the SharePoint folder you want to sync and click the “Sync” button. This will open the OneDrive sync client and prompt you to choose a location on your local drive to sync the folder to. Once you’ve selected a location, the folder will begin syncing, and any changes made to the SharePoint folder will be reflected in the local folder. More here: How to Sync SharePoint to Local Folder?

How do I map a SharePoint folder to a network drive?

To map a SharePoint folder to a network drive, Follow these steps. First, open File Explorer, Right-click on “This PC”, and choose “Map network drive.” Then, select the drive letter you want to use and enter the URL of the SharePoint site. Finally, enter your login credentials and select the document library you want to map. More: How to Map SharePoint to a Network Drive?

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!

11 thoughts on “How to Download a Folder from SharePoint Online using PowerShell?

  • I think it’s worth noting that in SharePoint Online our URLs had %20 representing spaces. The script can’t resolve a line that has those (at least for us). Replace with space and works fine.

    Reply
  • Hello. I am receiving the same as Noel. I run the script. It appears to run successfully, but I get nothing in the specified folder. For clarity, I am trying to download a folder several spots below the document library. I am trying get from Document Library/first level/second level/third level. I want to download the third level folder and all folders under it.

    1. Will your script do this?
    2. Why am I not getting any files while running the script?

    Thanks for any updates.

    Reply
    • I just tried the last script in the post and confirmed it just works fine. Does it give any message like:
      “Ensured Folder ‘C:\Docs\….’
      Downloaded File from ‘/sites/Retail/Shared Documents/2019/Active/invoice.xlsx'”.
      Are you running with the PnP.PowerShell module? Not the legacy SharePointPnPPowerShellOnline!

      Reply
  • Hi Salaudeen, I just tried using the script titled “Download a Folder with its Subfolders and Files from a Larger Document Libraries”, and the script appears to complete successfully (blue bar reaches the end, etc.), but the files are not transferred to my computer. There are no errors. Do you have any suggestions? Thanks!

    Reply
    • That’s odd! Are you sure you don’t find anything inside the folder you set for $TargetFolder or $DownloadPath parameters?

      Reply
  • Trying to download data about 100GB from SPO but we get an error after few hour
    Error Downloading Folder! Exception calling “OpenBinaryDirect” with “2” argument(s): “The operation has timed out”
    Error Downloading Folder! Exception calling “ExecuteQuery” with “0” argument(s): “The operation has timed out”

    Reply
  • Download-SPOFolder : Cannot process argument transformation on parameter ‘Folder’. Cannot convert the “Microsoft.SharePoint.Client.Folder” value of type “Microsoft.SharePoint.Client.Folder” to type “Microsoft.SharePoint.Client.Folder”.
    At line:1 char:20
    + Download-SPOFolder $Folder $DownloadPath
    + ~~~~~~~
    + CategoryInfo : InvalidData: (:) [Download-SPOFolder], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Download-SPOFolder

    Reply
    • Just close and Re-Open the PowerShell ISE. That should do the Magic.

      Reply
  • This script is almost perfect for me, but I have a large list and it fails on a folder that exceeds the threshold. Is there anyway to batch up the download of the files in a large folder?

    Reply
      • Is it possible for this to work on a root folder? E.g. /Sites/Marketing/Shared Documents instead of /Sites/Marketing/Shared Documents/New?

        It gives error “The property or field ‘Title’ has not been initialized.”, I believe as a result of line 11 “ListItemAllFields.ParentList”

        Reply

Leave a Reply

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