GMS 2.3+ Easy Online Highscores


Easy Online Highscores in GameMaker Studio using the Service

GM version:
GMStudio 2.3.2
Target platform: ALL
Latest change: 2021-09-22
Level: Intermediate (some GML knowledge)

In this tutorial you will learn how to add online highscore tracking in your game through the example project linked above and the service. GM Scoreboard is used by hundreds of developers and has been around for many years! Submit a player name and score such as at the end of a completed level. Scores are stored permanently in our secure database and can be accessed through our API. You can also retrieve the top 5 scores in your game or open a browser window showing up to the top 50 high scores for your game. You can customize your scoreboard page on our website with a banner, set scores, choose to show low to high or high to low and set how many scores should be tracked (up to the top 50).

You also get the added bonus of additional web traffic to your game as we feature player scores and games with links to download your game.


Step 1.

Create an account at, then login and create a scoreboard. Save. Take note of your scoreboard "tagid" it should look something like "78b57ded260f826682ad5d29ab433ca5"
This is a secret code, do not share it as this is the key to updating your scoreboard.

Step 2.
Open the project from the market place linked above and add it to your project. In your game project you will find an object named "obj_gmscoreboard" open it.
obj_gmscoreboard is a persistent object. Be sure it is added to the starting room of your project to run properly.

Step 3.
Open the create event for obj_gmscoreboard. Copy your tagid from the website to the function below. (you can also leave as is to use our example scoreboard instead)
setup_gmscoreboard("your tagid goes here");
This code sets the global.tagid variable as well as two other vars to help handle responses to https requests.

Step 4.
Run the game!
Press Enter to set a score the game will ask for your player name and a score and submit it automatically.
Press Shift to view submitted scores. The top 5 scores will be drawn on screen.
Press Ctrl to open a browser window to your online scoreboard page where the top 50 scores are shown.

After pressing shift you should see your top 5 scores listed here.

Step 5.
Modifying the example to your needs open the obj_gmscoreboard object.

Review the STEP event Examples:
In the step event of the obj_gmscoreboard I've tied the functionality of our helper functions to hot keys.
The Enter button calls the set_score(player_name, score) function which saves a score to the online database for your game.
The Shift button calls the get_scores(number) function which retrieves the top (upto 5) scores from the online database for your game.
The Ctrl button calls the show_scoreboard() function which simply opens to your scoreboard page in the browser, example below:


As long as the obj_gmscoreboard object exists you should have no issue using these functions throughout your project as needed. If you make a custom solution I recommend making this object invisible so it runs in the background.

//press enter to set a score.
if keyboard_check_pressed(vk_enter){

    //show message if you have not updated your tagid yet.
    if global.tagid == "78b57ded260f826682ad5d29ab433ca5"{
        show_message("This game is using the Example Scoreboard tagid \"78b57ded260f826682ad5d29ab433ca5\". Be sure to set your own scoreboard tagid in the create event of obj_gmscoreboard.");

    //get player name and score.
    player = get_string("What is the player's name?", "");
    player_score = get_integer("what is the player's score? (Use a high number to ensure it shows in the top 50 scores)", 1);

    //script to set a score. (uses the tagid set with the setup_gmscoreboard script)
    set_score(player, player_score);


//press shift to get current scores.
if keyboard_check_pressed(vk_shift){

//open your scoreboard page at to show your entire scoreboard.
if keyboard_check_pressed(vk_control){

Review the Async - HTTP event:
Here we process http request responses. You do not need to modify this event code. But you can if you want added functionality. For example you can modify what should happen if a score submission is a success, duplicate or failed.
The main purpose of this event is to update the global.gmscoreboard_scores variable with a ds_list of score data when the get_scores() function is called, this variable can be looped through to draw score data, see the DRAW EVENT below on how that works.

if ds_map_find_value(async_load, "id") == global.gmscoreboard_response{
    if ds_map_find_value(async_load, "status") == 0{
        result = json_decode(ds_map_find_value(async_load, "result"));

        status = result[? "status"];
        type = result[? "type"];
        error = result[? "message"];

        //on set-score request
        if type == "set-score"{
            if status == "success"{
                show_message("Score entered!");
                get_scores(5); //update score data.
            if status == "duplicate"{
            if status == "error"{

        //on get-score request
        if type == "get-scores"{
            if status == "success"{
                global.gmscoreboard_scores = result[? "scores"];

Review the Draw event example:
Here is an example of how to loop through all scores in the global.gmscoreboard_scores variable and displaying a string for each score. Modify the for loop however you need to display scores as needed.

draw_text(20,10,"Press Enter to set a score.");
draw_text(20,30,"Press Shift to manually request score data.");
draw_text(20,50,"Press Ctrl to open a web page to show your entire scoreboard.");

//example of drawing scores
if !ds_list_empty(global.gmscoreboard_scores){
    var num = ds_list_size(global.gmscoreboard_scores);
    draw_text(20,90,"Score data:");
    for (var i = 0; i < num; i++){
        var item = ds_list_find_value(global.gmscoreboard_scores, i);
        var player = item[? "player"];
        var player_score = item[? "score"];

        //draw a string of the data.
        draw_text(20,110+(20*i), string(i+1)+ ". " + player + " " + string(player_score));

The example project is not required to use Game Maker Scoreboard service.
Further documentation on how the API works can be found at

One added bonus of using service is we feature games as new high scores are added. Each scoreboard page can have links to your game on the iOS, android play, steam or your own website. Providing backlinks to your game which will help your ranking in search engines. (This feature will be complete next week)

Last edited:


It feels good to finally update GM Scoreboard and to create a new tutorial for it, it was running on aging servers for a long time. First launching in 2013 and then getting it's last major update back in 2016. But here we are in 2021 with a complete overhaul using the latest and greatest! I hope you all enjoy. It's a pretty simple system that takes about 5 minutes to setup and is very secure, but we have limited features. I am open to feedback and suggestions for future updates. If you need a more custom and or private solution there is always Appsurd's online highscore example.




my high scores are not working in html5 I looked at the console and found this

Access to XMLHttpRequest at '' from origin 'http://localhost:5000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.



I hope you can fix this!

edit: removed tag id sorry about that
Try again and let me know if it is fixed. It should work as is, but I guess html5 has some issues. I've changed some cors options in hopes that it will help.
Also even though you hid your tagid, it can still be seen when clicking the links in your post. I recommend creating a new scoreboard to get a new tagid after you finish testing with the current one.