2026-06-02: Bing Wallpaper Automatic Update Script
(This article is also available via the short link tomrei.ch/bingwallpaper)
Windows advertises the ability to automatically use the daily Bing image as your desktop wallpaper, but in practice I find it hit or miss — especially across multiple machines. Sometimes it updates, sometimes it doesn't, and sometimes it just quietly stops working. So I worked with GitHub Copilot to put together a small PowerShell script that does the job reliably, paired with a Scheduled Task that kicks it off when I unlock the machine.
The script fetches today's Bing image metadata, downloads the UHD version (falling back to the standard version if UHD isn't available), keeps the last 7 wallpapers around, logs what it's doing, and then sets the wallpaper via the Win32 API. It also skips itself entirely when running inside a Remote Desktop session so it doesn't fight with the remote desktop's wallpaper handling.
The script
Save this as C:\Scripts\BingWallpaper.ps1:
# ================================
# Bing Wallpaper Fetcher (No App)
# Keeps last 7 wallpapers + Logging
# ================================
# Where to save the wallpaper
$wallpaperDir = "$env:LOCALAPPDATA\BingWallpapers"
if (!(Test-Path $wallpaperDir)) { New-Item -ItemType Directory -Path $wallpaperDir | Out-Null }
# Log file
$logFile = Join-Path $wallpaperDir "BingWallpaper.log"
function Log($msg) {
$timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
Add-Content -Path $logFile -Value "$timestamp $msg"
}
Log "----- Script start -----"
# Skip if running inside a Remote Desktop session
if ($env:SESSIONNAME -and $env:SESSIONNAME -like "RDP-*") {
Log "Remote Desktop session detected ($env:SESSIONNAME). No action taken."
exit 0
}
# Bing API endpoint (today's image)
$bingApi = "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US"
# Fetch metadata
try {
$response = Invoke-RestMethod -Uri $bingApi -UseBasicParsing
} catch {
Log "ERROR: Failed to fetch Bing metadata: $_"
exit 1
}
$image = $response.images[0]
# Build URLs
$baseUrl = "https://www.bing.com"
$uhdUrl = $baseUrl + $image.urlbase + "_UHD.jpg"
$fullUrl = $baseUrl + $image.url
# Determine output filename
$filename = "BingWallpaper_$($image.startdate).jpg"
$filepath = Join-Path $wallpaperDir $filename
# If today's wallpaper already exists, exit early
if (Test-Path $filepath) {
Log "Already on latest wallpaper ($filename). No action taken."
exit 0
}
# Try UHD first, fall back if unavailable
try {
Invoke-WebRequest -Uri $uhdUrl -Method Head -TimeoutSec 5 -UseBasicParsing | Out-Null
$downloadUrl = $uhdUrl
Log "UHD available. Using UHD URL."
} catch {
$downloadUrl = $fullUrl
Log "UHD unavailable. Using fallback URL."
}
# Download the wallpaper
try {
Invoke-WebRequest -Uri $downloadUrl -OutFile $filepath -UseBasicParsing
Log "Downloaded new wallpaper: $filename"
} catch {
Log "ERROR: Failed to download wallpaper: $_"
exit 1
}
# Cleanup: keep only the 7 most recent wallpapers
$files = Get-ChildItem -Path $wallpaperDir -Filter "BingWallpaper_*.jpg" |
Sort-Object LastWriteTime -Descending
if ($files.Count -gt 7) {
$filesToDelete = $files | Select-Object -Skip 7
foreach ($f in $filesToDelete) {
Remove-Item $f.FullName -Force
Log "Deleted old wallpaper: $($f.Name)"
}
}
# Set wallpaper (registry + broadcast)
$code = @"
using System;
using System.Runtime.InteropServices;
public class Wallpaper {
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
}
"@
Add-Type $code
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name wallpaper -Value $filepath
[Wallpaper]::SystemParametersInfo(20, 0, $filepath, 3) | Out-Null
Log "Wallpaper applied successfully."
Log "----- Script end -----"
The VBScript launcher
The Scheduled Task launches a small VBScript wrapper instead of PowerShell directly. This is what
keeps the PowerShell window from briefly flashing on screen every time it runs. Save this as
C:\Scripts\BingWallpaper.vbs:
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ""C:\Scripts\BingWallpaper.ps1""", 0, False
Setting it up
- Create the folder
C:\Scriptsif it doesn't already exist. - Save the PowerShell script above as
C:\Scripts\BingWallpaper.ps1. - Save the VBScript above as
C:\Scripts\BingWallpaper.vbs. - Open Task Scheduler and create a new task (not a basic task).
- On the General tab, give it a name like "Bing Wallpaper Updater" and make sure it runs as the currently logged-in user (the default). Do not check "Run whether user is logged on or not" — the script needs to update the current user's desktop.
- On the Triggers tab, add a new trigger. Set "Begin the task" to On workstation unlock for any user (or your specific user). You can optionally add a second trigger at logon if you'd like it to run then as well.
-
On the Actions tab, add a new action with:
- Action: Start a program
- Program/script:
wscript.exe - Add arguments:
"C:\Scripts\BingWallpaper.vbs"
- On the Conditions tab, uncheck "Start the task only if the computer is on AC power" if you want it to run on battery too.
- Save the task and unlock your machine to test it.
Logs (and the cached wallpapers) end up in %LOCALAPPDATA%\BingWallpapers, which is handy if
you ever need to see why it didn't pick up today's image.