Downloading Bing Homepage Images as Desktop Wallpaper with Python

Analyzing the Bing API

Bing's homepage displays a different high-quality background image daily. The image data can be accessed through Bing's JSON API endpoint. The API URL follows this pattern:

https://www.bing.com/HPImageArchive.aspx?format=js&n=1

The n parameter specifies the number of images to retrieve (maximum 7). The response contains an images aray with metadata including the url field, which provides the relative path to the actual image file.

To construct the full image URL, prepend https://www.bing.com to the url value from the JSON response.

Downloading a Single Image

import json
import os
import urllib.request

json_endpoint = "https://www.bing.com/HPImageArchive.aspx?format=js&n=1"
base_url = "https://www.bing.com"
target_folder = os.path.expanduser("~/Pictures/BingWallpaper")

if not os.path.exists(target_folder):
    os.makedirs(target_folder)

response_file = os.path.join(target_folder, "bing_response.json")
urllib.request.urlretrieve(json_endpoint, response_file)

with open(response_file, "r", encoding="utf-8") as f:
    data = json.load(f)

image_path = data["images"][0]["url"]
full_image_url = base_url + image_path

current_date = data["images"][0]["startdate"]
target_file = os.path.join(target_folder, f"{current_date}.jpg")

urllib.request.urlretrieve(full_image_url, target_file)
print(f"Downloaded: {target_file}")

Setting Wallpaper on Ubuntu

GNOME-based Ubuntu systems allow wallpaper changes via the command line using gsettings:

gsettings set org.gnome.desktop.background picture-uri "file:///home/username/Pictures/BingWallpaper/20230715.jpg"

Retrieving Multiple Images

To fetch multiple wallpapers (up to 7 days of history):

json_endpoint = "https://www.bing.com/HPImageArchive.aspx?format=js&n=7"

The response will contain 7 image entries in the images array.

Random Wallpaper Selection

import os
import random

wallpaper_dir = os.path.expanduser("~/Pictures/BingWallpaper")
all_images = [f for f in os.listdir(wallpaper_dir) if f.endswith('.jpg')]
random_image = random.choice(all_images)
full_path = os.path.join(wallpaper_dir, random_image)

Complete Automation Script

#!/usr/bin/env python3
import json
import os
import random
import urllib.request
import datetime
import subprocess

HOME_DIR = os.path.expandvars('$HOME')
WALLPAPER_DIR = os.path.join(HOME_DIR, "Pictures", "BingWallpaper")
CONFIG_DIR = os.path.join(HOME_DIR, ".config", "bing_wallpaper")
MAX_IMAGES = 7
KEEP_DAYS = 30

def ensure_directories():
    for directory in [WALLPAPER_DIR, CONFIG_DIR]:
        if not os.path.exists(directory):
            os.makedirs(directory)

def fetch_image_metadata():
    endpoint = f"https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n={MAX_IMAGES}"
    cache_file = os.path.join(WALLPAPER_DIR, ".metadata.json")
    
    urllib.request.urlretrieve(endpoint, cache_file)
    
    with open(cache_file, "r", encoding="utf-8") as f:
        return json.load(f)

def download_images(metadata):
    base_url = "https://www.bing.com"
    downloaded = []
    
    for img in metadata["images"]:
        img_url = base_url + img["url"]
        img_name = img["startdate"] + ".jpg"
        save_path = os.path.join(WALLPAPER_DIR, img_name)
        
        if not os.path.exists(save_path):
            urllib.request.urlretrieve(img_url, save_path)
            print(f"Downloaded: {img_name}")
        
        downloaded.append(save_path)
    
    return downloaded

def set_random_wallpaper():
    available = [f for f in os.listdir(WALLPAPER_DIR) if f.endswith('.jpg')]
    
    if not available:
        print("No wallpapers available")
        return
    
    selected = random.choice(available)
    full_path = os.path.join(WALLPAPER_DIR, selected)
    uri = f"file://{full_path}"
    
    subprocess.run([
        "gsettings", "set", 
        "org.gnome.desktop.background", "picture-uri", 
        uri
    ])
    print(f"Wallpaper set to: {selected}")

def cleanup_old_images():
    cutoff = datetime.datetime.now() - datetime.timedelta(days=KEEP_DAYS)
    cutoff_str = cutoff.strftime('%Y%m%d')
    
    for filename in os.listdir(WALLPAPER_DIR):
        if filename.endswith('.jpg') and filename[:8] < cutoff_str:
            file_path = os.path.join(WALLPAPER_DIR, filename)
            os.remove(file_path)
            print(f"Removed old wallpaper: {filename}")

def main():
    ensure_directories()
    
    metadata = fetch_image_metadata()
    download_images(metadata)
    
    set_random_wallpaper()
    cleanup_old_images()

if __name__ == "__main__":
    main()

Scheduling Automatic Updates

Use cron to run the script automatically:

crontab -e

Add the following line to execute the script every 6 hours:

0 */6 * * * /usr/bin/python3 /path/to/bing_wallpaper.py

Key Points

  • The Bing API returns up to 7 recent images, identified by their startdate
  • Image filenames follow the YYYYMMDD format
  • The gsettings command requires the full file:// URI scheme
  • Automatic cleanup prevents storage bloat from accumulating old images

Tags: python web scraping Bing Wallpaper automation

Posted on Tue, 21 Jul 2026 16:59:28 +0000 by figment