Powershell script to download Azure DevOps project wiki

Azure DevOps has two types of wikis:
Code wikis (Git-backed) - which you can clone
Project wikis (non-Git) - stored in Azure DevOps' internal storage
The Azure DevOps UI gives you the URL to clone a code wiki locally, but does not provide a way to download a project wiki. Using Claude, I vibe coded a powershell script to download a project wiki. I’ve tested it only once and although it worked for my wiki, I can’t guarantee it generalises well to all wikis.
It requires a PAT token. You can create these from https://dev.azure.com/{Your_Organization}/_usersSettings/tokens. The only permission necessary is Wiki (Read). When adding a new PAT token, you'll need to click Show All Scopes then scroll to the bottom of the list to find it.
The script
For some reason, Hashnode (the platform which powers this blog) has messed up the formatting of this powershell script and tried to escape lots of characters. There shouldn't be any backslash characters (\) in the script, so if you remove all of them then it should work.
$org = "your-org"
$project = "your-project"
$wikiId = "your-wiki-id"
$pat = "your-personal-access-token"
Write-Host "Starting wiki backup..." -ForegroundColor Green
\(base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":\)pat"))
\(headers = @{Authorization = "Basic \)base64AuthInfo"}
# Get all pages
\(pagesUrl = "https://dev.azure.com/\)org/\(project/_apis/wiki/wikis/\)wikiId/pages?recursionLevel=full&api-version=7.0"
Write-Host "Fetching pages from: $pagesUrl" -ForegroundColor Cyan
try {
\(result = Invoke-RestMethod -Uri \)pagesUrl -Headers $headers
Write-Host "Wiki structure retrieved" -ForegroundColor Green
} catch {
Write-Host "Error fetching pages: $_" -ForegroundColor Red
exit
}
# Function to recursively process pages
function Process-WikiPage {
param($page)
# Skip the root page (path = "/")
if ($page.path -ne "/") {
Write-Host "Downloading: \((\)page.path)" -ForegroundColor Yellow
\(pageUrl = "https://dev.azure.com/\)org/\(project/_apis/wiki/wikis/\)wikiId/pages?path=\((\)page.path)&includeContent=true&api-version=7.0"
try {
\(content = Invoke-RestMethod -Uri \)pageUrl -Headers $headers
# Save to file
\(filePath = "wiki-backup\)($page.path).md"
\(directory = Split-Path \)filePath -Parent
if (\(directory -and !(Test-Path \)directory)) {
New-Item -Path $directory -ItemType Directory -Force | Out-Null
}
\(content.content | Out-File -FilePath \)filePath -Encoding UTF8
Write-Host "Saved: $filePath" -ForegroundColor Green
} catch {
Write-Host "Error downloading \((\)page.path): $_" -ForegroundColor Red
}
}
# Process subpages recursively
if (\(page.subPages -and \)page.subPages.Count -gt 0) {
foreach (\(subPage in \)page.subPages) {
Process-WikiPage -page $subPage
}
}
}
# Start processing from the root
Process-WikiPage -page $result
Write-Host "Backup complete!" -ForegroundColor Green



