How to build an automated NASA wallpaper switcher
The cosmos on your desktop
The stars above us have always been a source of wonder and knowledge. From a child I learnt about the Apollo programme which put humans on the moon, and managed to get Apollo 13 safely back to Earth.
Space is beautiful, full of nebulae, stars, planets and other astronomical objects, and luckily for us NASA has a free resource that we can use to see daily images taken from radio telescopes, observatories and satellites. In this how-to, we will learn how to use NASA’s free service to change our Windows 10 and 11 wallpaper to the latest astronomical image.
Getting a NASA API Key
NASA makes it really easy to use its resources, but to get the most from its resources we need an API key. API (Application Programming Interface) is a means for applications to use the resources provided by a company (or in our case, NASA.) The interface permits two or more machines to talk to one another and to make requests. In this project we will use the NASA API to get the daily Astronomy Picture of the Day (APOD.)
1. In a browser go to NASA’s API page and sign up for an API key. It is free and enables access to thousands of NASA resources.
2. Check your email for the API key, keep this handy but do not share it with anyone.
Setting up the Python environment
We need to install two extra Python libraries (modules) to provide extra features in our project code. The first is Win11Toast a popup notification tool for Windows 10 and 11 that we are using to show messages of success / failure when the app runs. The second library is pyinstaller, an exceptionally handy tool that packages Python projects and its dependencies into a single executable file. Previously we have used Auto Py to Exe, a GUI for this app to make executable files, but in this how-to, we just need a simple executable.
Before you start this how to, ensure that you have Python installed on your Windows 10 / 11 computer. We have a how to covering this.
Stay On the Cutting Edge: Get the Tom's Hardware Newsletter
Get Tom's Hardware's best news and in-depth reviews, straight to your inbox.
1. Open a Command Prompt. Press Windows key and type CMD and press Enter.
2. Use pip, the Python packaging tool to install the two libraries.
pip install win11toast
pip install pyinstaller
Writing the project code
With the API key and Python environment setup, now we can start writing the project code. We’re using the Thonny Python editor, but you can use any editor. Notepad++ and Microsoft’s VS Code are both great alternatives.
1. In a blank project page start by importing three libraries. Requests is used to request data from the NASA API. Ctypes enable our code to make changes to Windows DLLs. Win11toast, which imports just “toast” is used to make pop up notifications in Windows.
import requests
import ctypes
from win11toast import toast
2. Create an object called “url” and in there store the API request URL along with your API key. Your key should go after the = in the URL and remain inside the quotes.
url = "https://api.nasa.gov/planetary/apod?api_key=YOUR_API_KEY_HERE”
3. Create an object, “r” and use that to store the returned data from making a request to the NASA API.
r = requests.get(url)
4. Create the first conditional test to check if there is data in the object “r”. If that is true, then a series of tasks are performed.
if r:
5. Create an object called “APOD” and use it to store the JSON data for the APOD. Essentially this will give us the URL for the APOD image of the day which is stored as a value in the JSON object.
APOD = r.json()['url']
6. Create an object called “pic” and using the APOD object request the image from the NASA API. This downloads the file into memory, it is not yet written as a file to disk.
pic = requests.get(APOD, allow_redirects=True)
7. Add an additional if conditional test to check that the APOD update is a JPEG image and not a video. If there is no image for that day, a notification pops up in Windows to tell the user. NASA updates the APOD everyday, but some days the update is a YouTube video. Without this error handling test, the code will fail when a video update is provided.
if "jpg" not in APOD:
toast("No image for today, must be a YouTube video 📺")
8. Using an else condition, open a file called APOD.jpg in your user account’s Pictures directory and then write the image stored in memory to the file. Change the user account name to match your own, ours is lespo. Remember to include double back-slashes (\\) in the file path, otherwise Python will think we want to use escape characters.
else:
open("C:\\Users\\lespo\\Pictures\\APOD.jpg", "wb").write(pic.content)
9. Using ctypes, update the DLL to set the wallpaper to the APOD.jpg file. Remember to use the full file path.
ctypes.windll.user32.SystemParametersInfoW(20, 0, "C:\\Users\\lespo\\Pictures\\APOD.jpg", 3)
10. Using toast, create a pop up message to tell the user that the image has been changed. We can use emojis in our notifications, we sourced ours from Emojipedia.
toast("Enjoy the latest image from NASA 🚀")
11. Returning to the original if..else conditional statement (which handles if the APOD is an image or video), add an else condition and use it to print “Error” to the Python REPL.
else:
print("Error")
12. Save the code as apod.py and then test that it works in the editor. In Thonny we clicked Run and saw the notifications popup, along with the image being changed.
I can’t see the notifications!
When running the code, the Python REPL produced an error, “win11toast (<winsdk Windows Foundation.HResult object at 0x0000025163E315F0>,)” which didn’t mean a lot. Checking the Win11Toast Issues in Github we found that this error was produced when we chose to suppress popup notifications. The fix was easy.
1. Go to Settings and select System.
2. Select Notifications and actions and then turn on notifications. The granularity of which notifications you receive can be tweaked using the checkboxes.
3. Close the application window and retry your code to ensure that the notifications appear.
Creating an executable file
With the project code tested and working our attention turns to creating an executable file. By doing this we can drop the file on any Windows computer and it will just work. How it does this is by using pyinstaller which takes a snapshot of the Python environment in which the application will run. It then creates its own environment inside of the executable file. So all of the libraries that we used (requests, ctypes, win11toast etc) are packaged into the file meaning that we do not have to install them on the target system. It also means that we can drop the executable into the startup directory, but more on that later.
1. Open a Command Prompt. Press Windows key and type CMD and press Enter.
2. Navigate to the directory where the project code is.
3. Run pyinstaller with the -F argument and pass the name of the project file. Using -F will compact all of the Python environment into one file.
pyinstaller -F apod.py
4. Wait for the process to finish then close the Command Prompt.
5. Open the directory where the project code was saved and look for and open the “dist” directory. Inside is the executable file.
6. Double click on the file to test. The notification will popup to state that the image has been changed / it is a YouTube video. This proves that the file works.
Automatically changing the wallpaper
It isn’t too difficult to double-click on the executable to change our wallpaper, but what if Windows could do it for us? We’re going to move the executable file to the startup directory, where it will be run each time Windows starts.
1. Press Windows and R to open the run dialog and type shell:startup.
2. Copy the apod.exe file from the dist folder, into the Start-up folder. This will set the application to run when Windows starts.
3. Close the window and reboot Windows and watch for the notification in the panel.
Complete Code Listing
import requests
import ctypes
from win11toast import toast
url = "https://api.nasa.gov/planetary/apod?api_key=YOUR_API_KEY_HERE”
r = requests.get(url)
if r:
APOD = r.json()['url']
pic = requests.get(APOD, allow_redirects=True)
if "jpg" not in APOD:
toast("No image for today, must be a YouTube video 📺")
else:
open("C:\\Users\\lespo\\Pictures\\APOD.jpg", "wb").write(pic.content)
ctypes.windll.user32.SystemParametersInfoW(20, 0, "C:\\Users\\lespo\\Pictures\\APOD.jpg", 3)
toast("Enjoy the latest image from NASA 🚀")
else:
print("Error")
More Tutorials
Les Pounder is an associate editor at Tom's Hardware. He is a creative technologist and for seven years has created projects to educate and inspire minds both young and old. He has worked with the Raspberry Pi Foundation to write and deliver their teacher training program "Picademy".