Posted by: Chris Sept. 9, 2020, 3:50 p.m. |


  • Language
    • Python
    • Bash
  • Package
    • Discord Commands
  • Data
    • SQLite3
    • JSON
  • API
    • eBird

Brief Description

Repo Link

Birdy is the first project where I combined my love for birds and programming. I designed Birdy so birding communities on Discord could grab data from eBird. Although the birding community is not very big on Discord, I decided to create this project for fun and experience. 

There are various birding communities on Discord that are full of active birders. Like this one!  Birders on these servers submit observation checklists to eBird, which Birdy grabs data from. The idea was that birders on Discord could grab data right on their own server without having to visit the eBird website. 


To make Birdy, I used the Discord API and eBird API. The Discord API was use to have the bot communicate with the users of a server. The eBird API was used for querying observational data on birds.

Discord API

Birdy's main communication methods were made using the Python Discord API and the commands extension.

eBird API

The data Birdy uses was mostly grabbed from the eBird API, such as recent sightings from the past 30 days.

Google image search

In order to get images from the Google image search results to the Discord servers, I used a library that downloads Google images automatically. Although, this library did not actually do what I wanted it to. Every time I would run the script with a query, every single image would be downloaded. This meant my storage was going to fill up very quickly if I allowed people to search images unrestricted. 

Instead what I did, was look through the entire code base to see where the download occurs. I removed the lines that download the images, and instead returned the URLs of the images. This meant I wasn't storing a large amount of images. All that was stored were URL's that would get overwritten when a new query was entered.

eBird Wrapper

To use the eBird API, I had written a very simple wrapper for it. The wrapper is at this repository. This wrapper was mostly made with my own interests in mind, since the API has a lot of optional parameters that can be entered.


There were also other things I did that made Birdy a bit easier to use. For instance, if a user did not know the name of a bird, they could enter in what they thought it was. Say you wanted to find a Song Sparrow but you thought it was called a Schlong Sparrow, then Birdy will suggest a real bird name. Birdy suggests real bird names using a sequence matcher and a database of species names. You can choose to respond to Birdy with a yes or no.

Birdy can tell when you aren't putting in a real bird name, as well. 

Figure 1: Birdy knows you're joking around.

My favorite correction is this one:

Figure 2: Depressed Sparrow is not a real bird. Sparrows probably still can be depressed, though.

I also made plots for some commands like the top 5 command, that finds the top 5 species in a specified location.

Figure 3: Top 5 bird species at the time in Ireland. The country code for Ireland is IE.


Birdy has a help command that lists all the possible commands available. Below are the commands listed on the help message:

  • facts - Grabs a random fact on birds from this site
  • birbs - Grabs a random bird meme image (Gotta have memes on a Discord bot)
  • bird - Returns an image of the requested bird
  • rand - Returns a random bird image
  • recent - Returns recent sightings from requested location around the world
  • recent_notable - Returns recent notable sightings from requested location around the world
  • recent_species - Returns recent specified species sightings from requested location around the world
  • nearby - Returns sightings within a given radius and location
  • nearby_species - Returns sightings on a specified species of bird within a given radius and location
  • nearby_notable - Returns notable sightings within a given radius and location
  • nearest - Returns sightings of the nearest specified species within a given radius and location
  • historic - Returns sightings from any date as far back as the year 1800
  • top100 - Returns top 100 eBird users (Most observations)
  • stats - Returns how many checklists were made, how many species spotted and how many people contributed
  • adjacent_regions - Returns a list of regions adjacent to a given region
  • top_5 - Returns chart that plots top 5 species at a given location

Further Improvements

Since Birdy queries eBird for data, some results were not completely accurate. For instance, the top 5 command returns the top 5 species in a given location, but some sightings seem to be missing. To improve this, I would grab the basic dataset that eBird has available for download and I would query that dataset instead. There is a package called Auk written for the R language that queries the very large eBird dataset. Using Auk would make queries much more accurate.

I would also try hosting Birdy on some sort of server. At the moment, Birdy is not up so queries cannot be run on it. There are some free hosting services like PythonAnywhere I could have used, but this project is finished. Maybe in the future I may try hosting this project, and integrate it into this Django blog somehow.