Copy SharePoint files to local drive

There are a number of ways of copying or syncing files from SharePoint to your local drive or folder.

  • OneDrive Sync
  • WebDAV download
  • REST API
  • Microsoft Graph API

The OneDrive sync is pretty straightforward and there are lots of info online.

My goal is to automate this process without having to be logged in when it happens.

The following suggestions are from Copilot.

The WebDAV method

# Define source and destination paths
$sourcePath = "\\sharepointsite@SSL\DavWWWRoot\sites\YourSite\Shared Documents\FolderName"
$destinationPath = "C:\Local\BackupFolder"

# Create destination folder if it doesn't exist
if (!(Test-Path -Path $destinationPath)) {
    New-Item -ItemType Directory -Path $destinationPath
}

# Copy files
try {
    Copy-Item -Path "$sourcePath\*" -Destination $destinationPath -Recurse -Force
    Write-Host "Files copied successfully from SharePoint to local drive."
} catch {
    Write-Error "Error copying files: $_"
}

The REST API method

This method requires the PnP.PowerShell module for PowerShell.

Install-Module -Name PnP.PowerShell -Force

After installing the module you are ready to run this script.

# Connect to SharePoint Online
$siteUrl = "https://yourtenant.sharepoint.com/sites/yoursite"

Connect-PnPOnline -Url $siteUrl -Interactive

# Define the SharePoint folder and local destination
$sharePointFolder = "/Shared Documents/FolderName"

$localDestination = "C:\Local\BackupFolder"

# Create local folder if it doesn't exist
if (!(Test-Path -Path $localDestination)) {
    New-Item -ItemType Directory -Path $localDestination
}

# Get files from the SharePoint folder
$files = Get-PnPFolderItem -FolderSiteRelativeUrl $sharePointFolder -ItemType File

# Download each file
foreach ($file in $files) {
    $fileName = $file.Name
    $serverRelativeUrl = $file.ServerRelativeUrl
    $localPath = Join-Path -Path $localDestination -ChildPath $fileName

    Get-PnPFile -Url $serverRelativeUrl -Path $localDestination -FileName $fileName -AsFile -Force
    Write-Host "Downloaded: $fileName"
}

Write-Host "All files downloaded successfully."

The MS Graph API method

Using Microsoft Graph API to copy files from a SharePoint folder to a local drive via PowerShell is a powerful and flexible method, especially for modern SharePoint Online environments. Here's a step-by-step guide to help you set it up.

Prerequisites

Azure AD App Registration with delegated or application permissions:

Files.Read.All
Sites.Read.All
User.Read

Admin consent granted for the app. Client ID, Tenant ID, and Client Secret (or use device code flow for interactive login).

PowerShell modules:

Microsoft.Graph
Microsoft.Graph.Authentication

Install them if needed:

Install-Module Microsoft.Graph -Scope CurrentUser

To install the module for all users, change scope to AllUsers

Authentication (Device Code Flow)

Connect-MgGraph -Scopes "Files.Read.All", "Sites.Read.All"

Script to Download Files from SharePoint Folder

Here’s a simplified version that:

  • Connects to Microsoft Graph
  • Lists files in a SharePoint folder
  • Downloads them to a local path

This is some sample code:

# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Files.Read.All", "Sites.Read.All"

# Define variables
$siteName = "YourSiteName"
$siteDomain = "yourtenant.sharepoint.com"
$driveName = "Documents"  # Usually "Documents" for default doc library
$folderPath = "FolderName"  # Relative path inside the document library
$localPath = "C:\Local\BackupFolder"

# Create local folder if it doesn't exist
if (!(Test-Path -Path $localPath)) {
    New-Item -ItemType Directory -Path $localPath
}

# Get the site ID
$site = Get-MgSite -Hostname $siteDomain -SiteCollectionPath "/sites/$siteName"

# Get the drive ID (document library)
$drive = Get-MgSiteDrive -SiteId $site.Id | Where-Object { $_.Name -eq $driveName }

# Get items in the folder
$items = Get-MgDriveItemChild -DriveId $drive.Id -ItemId "root:/$folderPath"

# Download each file
foreach ($item in $items) {
    if ($item.File) {
        $downloadUrl = $item.AdditionalProperties["@microsoft.graph.downloadUrl"]
        $filePath = Join-Path -Path $localPath -ChildPath $item.Name
        Invoke-WebRequest -Uri $downloadUrl -OutFile $filePath
        Write-Host "Downloaded: $item.Name"
    }
}

Notes

  • This script uses Microsoft Graph SDK for PowerShell.
  • You can also use client credentials flow for unattended scripts (requires secret or certificate).
  • The @microsoft.graph.downloadUrl is a temporary URL to directly download the file.

Setup Azure AD app registration

To use Microsoft Graph API with client credentials flow in PowerShell, you'll need to set up an Azure AD app registration and use its credentials to authenticate without user interaction. This is ideal for automated scripts or background services.

Step-by-Step Setup

  1. Register an Azure AD App Go to Azure Portal → Azure Active Directory → App registrations → New registration.

     Name: e.g., GraphFileDownloader
     Supported account types: Choose Single tenant or Multitenant depending on your org.
     Redirect URI: Leave blank for client credentials flow.
  2. Create a Client Secret

    Go to Certificates & secrets → New client secret Save the value securely (you’ll use it in your script)

  3. Assign API Permissions

    Go to API permissions → Add a permission → Microsoft Graph

    Choose Application permissions Add:

     Sites.Read.All
     Files.Read.All

    Click Grant admin consent.

PowerShell Script Using Client Credentials

Install required module:

Install-Module Microsoft.Graph -Scope CurrentUser

Then use this script:

# Define credentials
$tenantId = "your-tenant-id"
$clientId = "your-client-id"
$clientSecret = "your-client-secret"

# Get token
$body = @{
    grant_type    = "client_credentials"
    scope         = "https://graph.microsoft.com/.default"
    client_id     = $clientId
    client_secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Method POST -Body $body
$accessToken = $tokenResponse.access_token

# Define SharePoint site and folder
$siteUrl = "https://yourtenant.sharepoint.com/sites/yoursite"
$headers = @{ Authorization = "Bearer $accessToken" }

# Get site ID
$siteInfo = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites/yourtenant.sharepoint.com:/sites/yoursite" -Headers $headers
$siteId = $siteInfo.id

# Get drive ID (usually "Documents")
$driveInfo = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites/$siteId/drives" -Headers $headers
$driveId = ($driveInfo.value | Where-Object { $_.name -eq "Documents" }).id

# Get files in folder
$folderPath = "FolderName"
$items = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/drives/$driveId/root:/$folderPath:/children" -Headers $headers

# Download files
$localPath = "C:\Local\BackupFolder"
if (!(Test-Path -Path $localPath)) {
    New-Item -ItemType Directory -Path $localPath
}

foreach ($item in $items.value) {
    if ($item.file) {
        $downloadUrl = $item."@microsoft.graph.downloadUrl"
        $filePath = Join-Path -Path $localPath -ChildPath $item.name
        Invoke-WebRequest -Uri $downloadUrl -OutFile $filePath
        Write-Host "Downloaded: $($item.name)"
    }
}

Summary

This script:

  • Authenticates using client credentials
  • Queries SharePoint via Graph API
  • Downloads files to a local folder

You can find the tenant-id by:

  1. Go to Azure Portal
  2. Navigate to Azure Active Directory
  3. Under Overview, look for: Tenant ID (also called Directory ID)

You can find the client-id by:

  1. In the Azure Portal, go to Azure Active Directory

  2. Click on App registrations

  3. Select your registered app (e.g., GraphFileDownloader) Under Overview, you'll see:

    Application (client) ID → This is your Client ID

Optional: Find Client Secret

If you've already created a client secret:

Go to your app → Certificates & secrets Under Client secrets, copy the Value (not the Secret ID)

Note: You can only copy the secret value when it's first created. If you lost it, you'll need to generate a new one.