Aerialbot
A simple yet highly configurable Mastodon bot that posts geotagged aerial imagery of a random location in the world.
Install / Use
/learn @doersino/AerialbotREADME
ærialbot
A simple yet highly configurable Mastodon bot that posts geotagged aerial imagery of a random location in the world.
In a bit more detail, whenever you run ærialbot, it...
- loads a shapefile from disk,
- efficiently generates a random point꙳ within the bounds of this shape,
- figures out which map tiles need to be downloaded to cover a certain area around the point in sufficient꙳ detail,
- downloads those map tiles from a provider of your choice real fast (a threadpool is involved!),
- stitches them together and crops the resulting image to precisely match the configured area,
- saves that to disk,
- and posts the image, optionally with a geotag.
Formerly a Twitter bot (until fascist billionaire acquisition shenanigans ensued).
As of November 2022, I've migrated all ærialbot instaces I had been running to Mastodon – follow them at @aerialbot@mastodon.social if you like.
You can also take a look at their now-silent Twitter equivalents...
- 🇺🇸 @americasquared, which tweets a satellite view of a randomly selected square mile of the United States once daily (examples shown below).
- 🇰🇷 @baekmanpyeong, which tweets a square sized one million (백만, baekman) pyeong (평, traditional Korean area unit, roughly 3.3058 m²), i.e. 1.818×1.818 km, somewhere in South Korea once each day.
- 🗾 @nihonmusuukei (Nihon mu sū kei = 日本無数景 ≈ 日本∞景, countless views of Japan), which tweets a square kilometer of Japan every day.
- 🇩🇪 @zehnhektar, which tweets a square sized 316×316 meters (Zehn Hektar = ten hectacres) somewhere in Germany every 24 hours.
- 🌍 @placesfromorbit, a "worldwide" instance that tweets a 5×5 km square every 6 hours.
- 🌆 @citiesatanangle, an instance that tweets tightly-zoomed 45-degree views of (sub)urban areas around the world every 12 hours.
...and formerly-active instances run by others (let me know – by, say, filing an issue – if you want yours to be included):
- 🇩🇰 @DanskKvadrat (run by @Wegge), which focuses on Denmark and tweets a 2×2 km square every 4 hours.
- 🇷🇴 @AerianRobot (not sure who runs it), which tweets a square-shaped portion of Romania twice each day.
- 🇳🇱 @NL_kwadraat (run by @michelbinkhorst), which tweets a 2×2 km square of the Netherlands three times each day.
- 🇳🇱 @amsUpTop (run by @kns008), which tweets a random square of Amsterdam or its surroundings once a day.
- 🇹🇷 @turkeyfromorbit (run by @btutal and also active on Instagram), where an ærialbot instance tweets square-kilometer-sized satellite images of Turkey while an earthacrosstime instance posts videos as described in the next sentence.
Also check out earthacrosstime (newly also posting on @aerialbot@mastodon.social), a "sibling" bot that posts timelapse videos showcasing how random locations in the world have changed since 1984.


Posting can be disabled, meaning that this tool can serve as a high-resolution map downloader in a pinch. It newly – as of October 2021 – supports the 45-degree imagery available on Google Maps, such as this view of Barcleona, centered on the Basílica de la Sagrada Família.
Features
Here's why ærialbot is a Good Bot:
- Configurability: Take a look at
config.sample.ini– you can supply your own shapefile (and, optionally, a shapefile of areas to exclude; or instead define a fixed point), control output verbosity, set a different map tile provider (there's a bunch of presets, including oblique views), define the filenames of the result images, scale them to your preferred size, define the text of the post, and more! - ꙳Correctness: Because neighboring meridians are closer at the poles than at the equator, uniformly sampling the allowable range of latitudes would bias the generated random points toward the poles. Instead, ærialbot makes sure they are distributed with regard to surface area. For the same reason (plus the Mercator projection), the number of map tiles required to cover an area depends on the latitude – ærialbot accounts for this, too.
- ꙳Automatic zoom level determination: Simply define the dimensions of the desired area around the generated point – ærialbot will then take care of dialing in a (more than) sufficient zoom level.
- Comes with batteries included: The
shapefiles/directory contains a number of shapefiles to get you started, along with a guide on preparing further shapefiles for use with ærialbot. - Tile grabbing performance: Multiple map tiles are downloaded in parallel, and there's a snazzy progress indicator (as you can see in the GIF below) to keep you updated on the download progress.
- Logging: Keeps a log file – whether that's for debugging or reminiscing is your call. Again, you can disable this easily.

Usage
Setup
Being a good Python 3 citizen, ærialbot integrates with venv or similar packages to avoid dependency hell. Run the following commands to get it installed on your system:
$ git clone https://github.com/doersino/aerialbot
$ python3 -m venv aerialbot
$ cd aerialbot
$ source bin/activate
$ pip3 install -r requirements.txt
(To deactivate the virtual environment, run deactivate.)
One of the dependencies, Shapely, requires the GEOS library for performing operations on two-dimensional vector geometries, which you may need to install first as described here.
Configuration
Copy config.sample.ini to config.ini (via cp config{.sample,}.ini for some Unix wizard vibes or just with your file manager like us normals), open it and modify it based on the (admittedly wordy) instructions in the comments.
See shapefiles/README.md for advice regarding finding shapefiles of the region you're interested in and preparing them for use with ærialbot.
Feel free to file an issue if anything's unclear!
Running
Once you've set everything up and configured it to your liking, run:
$ python3 aerialbot.py
That's basically it!
If you want your bot to post at predefined intervals, use cron, runwhen or a similar tool. To make cron work with venv, you'll need to use bash and execute the activate script before running ærialbot (in this example, it runs every four hours at 30 minutes past the hour):
30 */4 * * * /usr/bin/env bash -c 'cd /PATH/TO/aerialbot && source bin/activate && python3 aerialbot.py'
Pro tip: If you want to host multiple instances of ærialbot, you don't need multiple copies of the code – multiple config files suffice: simply run python3 aerialbot.py one-of-your-config-files.ini.
Uber pro tip: You can maintain a base config (say, with your directory setup, image size settings, and Mastodon credentials) plus individual configs (say, for shapefiles and area sizes), then supply two or more config files on the command line (the later ones override settings defined previously): python3 aerialbot.py base.ini specific.ini tweak.ini.
1337 H4x0r pro tip: Run python3 aerialbot.py --help to learn about some secret CLI options!
FAQ
Why the name?
Because it's cute and I like the "æ" ligature.
Why did you make this tool?
Because satellite imagery can be extremely beautiful, and I was looking for a way of regularly receiving high-resolution satellite views of arbitrary locations such as the center pivot irrigation farms of the American heartland or squares of the Jefferson grid in my timeline.
Note that I've built this tool (along with its predecessor gomati) during the COVID-19 pandemic – when it was, you know, just kinda nice to see the great outdoors somehow.
Does this violate Google's terms of use?
*(That's only relevant if you configure ærialbot to download tiles from Google Maps, which is the default source – but [other tile providers do exist](htt
Related Skills
node-connect
339.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.9kCommit, push, and open a PR
