How to Export PowerShell Scripts from Microsoft Intune

How to Export PowerShell Scripts from Microsoft Intune

If you manage a modern workplace, you’ve likely encountered a strange limitation in the Microsoft Intune Admin Center: once you upload a PowerShell script, there is no “Download” or “View” button to get it back.

Whether you need to audit old code, migrate to a new tenant, or simply lost your local copy, recovering these scripts is a common challenge for IT Admins. In this guide, we’ll show you how to use the Microsoft Graph API to pull your scripts back down to earth.

Why is there no “Download” button in Intune?

Microsoft treats Intune as a deployment engine rather than a script repository. When you upload a .ps1 file, Intune converts the text into a Base64 encoded string and stores it in the service. While the portal shows you the script’s name and assignment status, the underlying code is hidden from the UI to keep the interface clean and focus on management rather than development.

Prerequisites: What you need before starting

Before you can run the export process, ensure you have the following:

  • Permissions: You must have the Intune Administrator or Global Administrator role.
  • PowerShell Module: You need the Microsoft Graph SDK installed. You can install it by running: Install-Module Microsoft.Graph -Scope CurrentUser
  • A Local Folder: Create a folder (e.g., C:\IntuneScripts) where you want the exported files to land.

The PowerShell Export Script

Copy the following script into your PowerShell ISE or VS Code. This script automates the retrieval and decoding process for every script in your tenant.

PowerShell

Intune Powershell Export Script
# 1. Connect to Microsoft Graph with the necessary permissions
Connect-MgGraph -Scopes "DeviceManagementScripts.Read.All"

# 2. Define where you want to save your scripts
$exportPath = "C:\IntuneScripts"
if (!(Test-Path $exportPath)) { New-Item -ItemType Directory -Path $exportPath }

# 3. Fetch the list of all scripts
$baseUrl = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
$scripts = (Invoke-MgGraphRequest -Method GET -Uri $baseUrl).value

Write-Host "Found $($scripts.Count) scripts. Starting export..." -ForegroundColor Cyan

foreach ($s in $scripts) {
    # We must call the specific ID to get the 'scriptContent' property
    $detailUri = "$baseUrl/$($s.id)"
    $scriptDetail = Invoke-MgGraphRequest -Method GET -Uri $detailUri
    
    $fileName = $s.displayName -replace '[\\\/\:\*\?\"<>\|]', '_' # Sanitize filename
    $fileName = "$fileName.ps1"
    
    if ($null -ne $scriptDetail.scriptContent) {
        # Decode the Base64 content
        $base64 = $scriptDetail.scriptContent
        $bytes = [System.Convert]::FromBase64String($base64)
        $decodedText = [System.Text.Encoding]::UTF8.GetString($bytes)

        # Save to file
        $decodedText | Out-File -FilePath "$exportPath\$fileName" -Encoding utf8
        Write-Host "Exported: $fileName" -ForegroundColor Green
    } else {
        Write-Warning "Could not find content for $($s.displayName)"
    }
}

Write-Host "Process Complete! Files are located in $exportPath" -ForegroundColor White

Step 1: Connecting to Microsoft Graph

The script uses Connect-MgGraph with the DeviceManagementScripts.Read.All scope. This is the “key” that opens the Intune script vault. When you run this, a browser window will open asking you to sign in and “Consent on behalf of your organization.”

Step 2: Decoding Base64 Script Content

The API returns your code in a format called Base64. To make it readable, the script takes that string, converts it back into a byte array, and finally translates it into standard UTF8 text before saving it as a .ps1 file.

Exporting Remediation Scripts

Remediation scripts are stored differently than standard scripts because they come in pairs (a Detection script and a Remediation script). To export these, you change the API endpoint to deviceHealthScripts.

The Updated Script Snippet:

PowerShell

Exporting Remediation Scripts
# 1. SET YOUR PATH HERE (Change this to a folder you own)
$exportPath = "c:\temp"

# 2. Create the folder if it doesn't exist
if (!(Test-Path $exportPath)) { 
    New-Item -ItemType Directory -Path $exportPath -Force 
}

# 3. Re-run your Remediation Export
$baseUrl = "https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts"
$remediations = (Invoke-MgGraphRequest -Method GET -Uri $baseUrl).value

foreach ($r in $remediations) {
    $detailUri = "$baseUrl/$($r.id)"
    $details = Invoke-MgGraphRequest -Method GET -Uri $detailUri
    $safeName = $r.displayName -replace '[\\\/\:\*\?\"<>\|]', '_'

    Write-Host "Exporting: $safeName" -ForegroundColor Cyan

    # Export Detection Script
    if ($null -ne $details.detectionScriptContent) {
        $detBytes = [System.Convert]::FromBase64String($details.detectionScriptContent)
        $detPath = Join-Path $exportPath "$safeName`_Detection.ps1"
        [System.Text.Encoding]::UTF8.GetString($detBytes) | Out-File -FilePath $detPath -Force
    }

    # Export Remediation Script
    if ($null -ne $details.remediationScriptContent) {
        $remBytes = [System.Convert]::FromBase64String($details.remediationScriptContent)
        $remPath = Join-Path $exportPath "$safeName`_Remediation.ps1"
        [System.Text.Encoding]::UTF8.GetString($remBytes) | Out-File -FilePath $remPath -Force
    }
}

Write-Host "Success! Files saved to: $exportPath" -ForegroundColor Green

Troubleshooting “403 Forbidden” Errors

If you run the script and see a red 403 Forbidden error, it usually means your session doesn’t have the right permissions.

  • The Fix: Run Disconnect-MgGraph and then run the Connect-MgGraph command from the script again.
  • Check Scopes: Ensure you are using the specific scope DeviceManagementScripts.Read.All. Without this exact permission, the Graph API will block the request even if you are a Global Admin.

Conclusion

While the missing download button in Intune is a hurdle, the Microsoft Graph API makes it possible to manage your scripts programmatically. By using this export script, you can ensure your hard-coded logic is always backed up and available for review.