Skip to content

Instantly share code, notes, and snippets.

@birdstream
Created October 10, 2025 19:10
Show Gist options
  • Save birdstream/d29b4b36537f928682c5586b62bfde42 to your computer and use it in GitHub Desktop.
Save birdstream/d29b4b36537f928682c5586b62bfde42 to your computer and use it in GitHub Desktop.
Egde backup
<#
.SYNOPSIS
Backup or restore Microsoft Edge profiles locally (no account sync).
.DESCRIPTION
- BACKUP: Save Bookmarks only or full profile(s) to a chosen folder as ZIP files.
- RESTORE: Restore Bookmarks or full profile(s) from a file/folder/ZIP.
Works for the current Windows user only.
.PARAMETER Mode
backup | restore (default: backup)
.PARAMETER Dest
Backup destination folder (default: Desktop\EdgeBackup)
.PARAMETER Profile
Profile name, e.g. "Default", "Profile 1" (default: Default)
.PARAMETER AllProfiles
Include all profiles under Edge's User Data path.
.PARAMETER OnlyBookmarks
Operate on Bookmarks file only (Bookmars JSON).
.PARAMETER Source
For restore: path to a Bookmarks file, a ZIP, or an extracted profile folder.
.EXAMPLE
.\edge_backup.ps1 -Mode backup -AllProfiles -OnlyBookmarks
Backs up Bookmarks JSON for all profiles to Desktop\EdgeBackup
.EXAMPLE
.\edge_backup.ps1 -Mode backup -Profile "Default" -Dest D:\Backups
Full-profile ZIP backup of "Default" to D:\Backups
.EXAMPLE
.\edge_backup.ps1 -Mode restore -OnlyBookmarks -Profile "Default" -Source .\Edge-Bookmarks-Default.json
Restores only Bookmarks to the Default profile
.EXAMPLE
.\edge_backup.ps1 -Mode restore -Source .\Edge-Profile-Default.zip
Restores full "Default" profile from ZIP
#>
[CmdletBinding()]
param(
[ValidateSet('backup','restore')][string]$Mode = 'backup',
[string]$Dest = "$(Join-Path $env:USERPROFILE 'Desktop\EdgeBackup')",
[string]$Profile = 'Default',
[switch]$AllProfiles,
[switch]$OnlyBookmarks,
[string]$Source
)
$ErrorActionPreference = 'Stop'
function Ensure-EdgeClosed {
$p = Get-Process -Name "msedge" -ErrorAction SilentlyContinue
if ($p) {
Write-Host "Microsoft Edge is running. Attempting to close..." -ForegroundColor Yellow
$p | ForEach-Object { $_.CloseMainWindow() | Out-Null }
Start-Sleep -Seconds 2
$p = Get-Process -Name "msedge" -ErrorAction SilentlyContinue
if ($p) {
Write-Host "Forcing Edge to close..." -ForegroundColor Yellow
$p | Stop-Process -Force
}
}
}
function Get-EdgeBase {
$base = Join-Path $env:LOCALAPPDATA 'Microsoft\Edge\User Data'
if (-not (Test-Path $base)) { throw "Edge User Data path not found: $base" }
return $base
}
function Get-Profiles([string]$base) {
$dirs = Get-ChildItem -LiteralPath $base -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match '^(Default|Profile \d+)$' }
return $dirs
}
function Backup-Bookmarks([System.IO.DirectoryInfo[]]$profiles, [string]$dest) {
New-Item -ItemType Directory -Force -Path $dest | Out-Null
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
foreach ($prof in $profiles) {
$src = Join-Path $prof.FullName 'Bookmarks'
if (Test-Path $src) {
$out = Join-Path $dest ("Edge-Bookmarks-{0}-{1}.json" -f $prof.Name, $stamp)
Copy-Item -LiteralPath $src -Destination $out -Force
Write-Host "Saved: $out"
} else {
Write-Warning "No Bookmarks file in $($prof.Name)"
}
}
}
function Backup-Full([System.IO.DirectoryInfo[]]$profiles, [string]$dest) {
New-Item -ItemType Directory -Force -Path $dest | Out-Null
foreach ($prof in $profiles) {
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$zip = Join-Path $dest ("Edge-Profile-{0}-{1}.zip" -f $prof.Name, $stamp)
Write-Host "Creating archive: $zip"
# Collect files excluding heavy cache dirs
$files = Get-ChildItem -LiteralPath $prof.FullName -Recurse -File |
Where-Object { $_.FullName -notmatch '\\(Cache|Code Cache|GPUCache|DawnCache)\\' }
if ($files.Count -eq 0) {
Write-Warning "No files to archive in $($prof.FullName)"
continue
}
if (Test-Path $zip) { Remove-Item $zip -Force }
Compress-Archive -Path $files.FullName -DestinationPath $zip -CompressionLevel Optimal
Write-Host "Saved: $zip"
}
}
function Restore-Bookmarks([string]$source, [string]$targetProfilePath) {
$dst = Join-Path $targetProfilePath 'Bookmarks'
if (-not (Test-Path $source)) { throw "Bookmarks source not found: $source" }
if (-not (Test-Path $targetProfilePath)) { New-Item -ItemType Directory -Force -Path $targetProfilePath | Out-Null }
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
if (Test-Path $dst) {
Copy-Item -LiteralPath $dst -Destination ($dst + ".bak-$stamp") -Force
}
Copy-Item -LiteralPath $source -Destination $dst -Force
Write-Host "Restored Bookmarks to: $dst"
}
function Restore-Full([string]$source, [string]$base) {
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$temp = Join-Path ([System.IO.Path]::GetTempPath()) ("EdgeRestore-$stamp")
New-Item -ItemType Directory -Force -Path $temp | Out-Null
if ((Test-Path $source) -and (Get-Item $source).PSIsContainer) {
Write-Host "Using extracted folder as source: $source"
$root = $source
} elseif ($source -and (Test-Path $source) -and ($source -like '*.zip')) {
Write-Host "Expanding ZIP: $source"
Expand-Archive -LiteralPath $source -DestinationPath $temp -Force
$root = $temp
} else {
throw "Provide -Source as a ZIP file or extracted profile folder containing 'Default' / 'Profile X'."
}
$profileDirs = Get-ChildItem -LiteralPath $root -Directory -Recurse |
Where-Object { $_.Name -match '^(Default|Profile \d+)$' }
if (-not $profileDirs) { throw "No profile folders found in restore source." }
foreach ($p in $profileDirs) {
$dest = Join-Path $base $p.Name
if (Test-Path $dest) {
$bak = "$dest.bak-$stamp"
Write-Host "Backing up existing: $dest -> $bak"
Rename-Item -LiteralPath $dest -NewName (Split-Path -Leaf $bak)
}
Write-Host "Restoring profile: $($p.Name)"
Copy-Item -LiteralPath $p.FullName -Destination $dest -Recurse -Force
}
Write-Host "Restore complete."
}
try {
Ensure-EdgeClosed
$base = Get-EdgeBase
$profiles = @()
if ($AllProfiles) {
$profiles = Get-Profiles -base $base
if (-not $profiles) { throw "No profiles found under $base" }
} else {
$path = Join-Path $base $Profile
if (-not (Test-Path $path)) { throw "Profile not found: $path" }
$profiles = ,(Get-Item $path)
}
if ($Mode -eq 'backup') {
if ($OnlyBookmarks) {
Backup-Bookmarks -profiles $profiles -dest $Dest
} else {
Backup-Full -profiles $profiles -dest $Dest
}
} else {
if ($OnlyBookmarks) {
if (-not $Source) { throw "Provide -Source path to a Bookmarks JSON to restore." }
Restore-Bookmarks -source $Source -targetProfilePath $profiles[0].FullName
} else {
if (-not $Source) { throw "Provide -Source path to a ZIP or extracted folder to restore." }
Restore-Full -source $Source -base $base
}
}
} catch {
Write-Error $_.Exception.Message
exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment