Using Python and ChatGPT to Build an API Client for a Game

Discover how to use Python and ChatGPT to create a simple API client for Age of Empires IV stats and visualize the data in a few prompts.

Identifying HTTP API Requests

Firstly, for writing an API client we need to read the documentation or identify HTTP requests responsible for chosen actions. As I didn’t expect any documentation and the API was used by the fronted application I used the network tab in my browser to inspect HTTP traffic. I opened the Age of Empires IV: Ranked Seasons website which is actually listing all of the players from each season, their position, rank points and some additional details such as win/lost etc.

Ranked Seasons Leaderboards — Age of Empires IV

After right-clicking and choosing “Inspect”, I opened the browser’s developer tools and investigated what HTTP requests are being sent to the server and how responses look like. Those are two crucial things in terms of writing API client. Of course, there are more complex solutions for HTTP traffic interception such as Burp Suite, Postman or Zed Attack Proxy (ZAP) but at that time I wanted to develop the client quickly…

I was sitting at my friend’s place just after one match and just before another one.

Using a navigation menu from the bottom of the website, I opened the last page to identify what HTTP request is sent to obtain data about players. I took a look at the Network tab in developer tools and observed the following HTTP response containing details visible on the frontend. Those details provided valuable info about players such as userName, rank, rankLevel, win, losses etc.

HTTP Response Returned by EventLeaderboard API Endpoint

Based on those data, we could create some decent metrics and analyse them. After identifying the HTTP response, I needed HTTP request which was sent to the server to obtain the data. As I was really lazy, I didn’t want to make too many clicks to get raw HTTP content, so I copied cURL command by right-clicking on “EventLeaderboard” name in the following way:

Screenshot Presenting Network Tab in Developer Tools

Now, I have all of the requirements what I needed for my assistant to start working on the client.

 

Developing API Client

As we have both HTTP request and response, we can deve… ekhm delegate a development of the API client to ChatGPT. I used cURL from my clipboard and provided the following prompt describing both HTTP request and the response:

generate me a Python API client which will pull all of the data 
from the API which can be accessed by running the following cURL 
command. Current page is 395 and this is the last page. The first page is 1.
Create a client which will pull data from all of those pages. 

curl 'https://api.ageofempires.com/api/ageiv/EventLeaderboard' \
  -H 'authority: api.ageofempires.com' \
  -H 'accept: */*' \
  -H 'accept-language: pl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7' \
  -H 'content-type: application/json' \
  -H 'origin: https://www.ageofempires.com' \
  -H 'referer: https://www.ageofempires.com/' \
  -H 'sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0' \
  --data-raw '{"region":7,"versus":"players","matchType":12,"teamSize":"1v1","searchPlayer":"","page":395,"count":100,"isConsole":false}' \
  --compressed

The following JSON data are returned by the above API request:
{
    "count": 39479,
    "items": [
        {
            "gameId": "4",
            "userId": null,
            "rlUserId": 11743000,
            "userName": "sergio.zapparrata",
            "avatarUrl": "https://avatars.steamstatic.com/fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb_full.jpg",
            "playerNumber": null,
            "elo": 161,
            "eloRating": 0,
            "eloHighest": 161,
            "rank": 39401,
            "rankTotal": 39479,
            "region": "2074389",
            "wins": 3,
            "winPercent": 42.86,
            "losses": 4,
            "winStreak": 3,
            "rankLevel": "Bronze I",
            "rankIcon": "team_bronze_1.png",
            "leaderboardKey": "8872bc28"
        },
}

Yes, that’s all of what I needed to provide as a prompt to get a basic Python API client written in seconds!

ChatGPT answered without trouble as presented below:

Screenshot from ChatGPT with Initial Client Code

Here is the code from above truncated screenshot:

import requests
import json

def fetch_data(page):
    url = 'https://api.ageofempires.com/api/ageiv/EventLeaderboard'
    headers = {
        'accept': '*/*',
        'accept-language': 'pl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7',
        'content-type': 'application/json',
        'origin': 'https://www.ageofempires.com',
        'referer': 'https://www.ageofempires.com/',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
    }
    payload = {
        'region': 7,
        'versus': 'players',
        'matchType': 12,
        'teamSize': '1v1',
        'searchPlayer': '',
        'page': page,
        'count': 100,
        'isConsole': False
    }
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

def get_all_pages():
    all_data = []
    total_pages = 395  # Total number of pages
    for page in range(1, total_pages + 1):
        data = fetch_data(page)
        all_data.extend(data['items'])
        print(f'Fetched data for page {page}')
    return all_data

# Fetch data from all pages
all_page_data = get_all_pages()

# You can then process this data as needed, for example, saving to a file
with open('age_of_empires_data.json', 'w') as file:
    json.dump(all_page_data, file)

print("Data fetching complete.")

This code worked completely fine and for my small task, it was good enough to pull interesting data. I was amazed that the provided cURL command was processed successfully and provided an example HTTP response was also sufficient for my new assistant to get sh*t done.

 

Creating Diagrams

I’m not a data scientist and I use visualisation libraries on rare occasions. Developing a Python API client wouldn’t take me much more than a couple of minutes but creating some diagrams would require me to read some documentation or find some ready to use code on the Internet. I created another prompt to obtain a chart with rank levels and to be honest, I didn’t have much expectations at this point.

In the next prompt, I kindly thanked my new assistant for the good job done with the API client and I asked for the chart with all players per ranks:

Screenshot from ChatGPT Presenting How It Tries to Provide Me a Chart

As you can observe, there was an “Error analysing” error returned in the output. It looks like the process failed because no sample data were provided and my new assistant didn’t pull them from the API. However, ChatGPT performed an initial analysis and created Python code for the visualisation. After clicking on the small terminal button in the bottom right corner presented in the above screenshot, I was able to see the following analysis code:

Screenshot from ChatGPT Used to Create a Chart

This code couldn’t be used by ChatGPT as it needed some sample data but I could use this code in my newly created Python API client. I wanted to have the chart saved in the file, so I asked for it in my next prompt:

Finally, after merging the code and running the client, I got the following chart as an output:

Number of Age of Empires IV Players per Rank Level

This is exactly what I wanted to achieve! I was able to get this by identifying one API endpoint and making 3 prompts to ChatGPT… It could take me 15 minutes or less?

I need to note that I didn’t adjust the prompts for the purposes of this article. All of the presented prompts and screenshots are from ChatGPT history. I just wrote the prompts one time a few weeks ago when I was creating this client.

If you’re curious about my position on the ladder — at the time of creating this diagram I had Gold II rank which can be seen as one of the most common intermediate ranks. Unfortunately, the holiday time was not long enough for me to achieve Platinum but who knows… maybe someday…

 

Final Python Code

import requests
import json
import matplotlib.pyplot as plt
import pandas as pd


def fetch_data(page):
    url = 'https://api.ageofempires.com/api/ageiv/EventLeaderboard'
    headers = {
        'accept': '*/*',
        'accept-language': 'pl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7',
        'content-type': 'application/json',
        'origin': 'https://www.ageofempires.com',
        'referer': 'https://www.ageofempires.com/',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
    }
    payload = {
        'region': 7,
        'versus': 'players',
        'matchType': 12,
        'teamSize': '1v1',
        'searchPlayer': '',
        'page': page,
        'count': 100,
        'isConsole': False
    }
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

def get_all_pages():
    all_data = []
    total_pages = 395  # Total number of pages
    for page in range(1, total_pages + 1):
        data = fetch_data(page)
        all_data.extend(data['items'])
        print(f'Fetched data for page {page}')
    return all_data

# Fetch data from all pages
all_page_data = get_all_pages()

# You can then process this data as needed, for example, saving to a file
with open('age_of_empires_data.json', 'w') as file:
    json.dump(all_page_data, file)

print("Data fetching complete.")

# Convert the data to a DataFrame
df = pd.DataFrame(all_page_data)

# Count the number of users per rank level
rank_counts = df['rankLevel'].value_counts()

# Plotting
plt.figure(figsize=(10, 6))
rank_counts.plot(kind='bar')
plt.title('Number of Users per Rank Level')
plt.xlabel('Rank Level')
plt.ylabel('Number of Users')
plt.xticks(rotation=45)
plt.tight_layout()

plt.savefig('rank_level_distribution.png')
plt.show()

You can run the code by executing the following commands in a terminal:

# install Python dependencies
pip3 install requests pandas matplotlib

# run the code saved in app.py file
python3 app.py

#python 

Using Python and ChatGPT to Build an API Client for a Game
1.45 GEEK