Mouse Macro Recorder tutorial

Mouse macro recorder a tutorial

Mouse Macro Recorder tutorial

There are so many free mouse and keyboard recorders

All of them just one download away

So if that is all you need:

This tutorial may not be for you

Because in this tutorial

I will teach you how to make your

Very own unique mouse macro recorder.

And its simple and totally free,

All you need do is to hear me out:

Then copy and paste some text or

Click download!

Think you can manage that?


Why? make your own mouse macro recorder!

Well to me at least a few things come to mind when trying to answer,

  1. You will know exactly how it works so that you can make it do even more like also using as a keyboard macro program.
  2. Its a great way to see what learning a free scripting-language can do for you.
  3. Having your own unique mouse macro recorder program may help with not being detected in some games.

After reading this tutorial you will be able to make you very own mouse recorder using the scripting language AutoHotkey.

Degree of difficulty:


All you need is:

As always you will find the free download links at the end of this page, one for both the finished working script, with all the shown lines and also a compiled exe with the same for those of you who only wish to try the mouse macro recorder.


Example video: (2:26)

Mouse Macro Recorder a tutorial demo


What will learning to make it yourself do for you?

I can say that this is not a mouse recorder that thousands of others are using, like all those free recorders out there where you download some .exe and you first need to get familiar with its controls: You will already know exactly what the mouse macro recorder is doing and when its recording or playing back and so on.

You will learn all you need to know about the recorder before using it, and it will also be a lot easier for you to manually edit the scripts that you recorded to make them even more effective.

You can use it as an auto clicker or work automator, in things like games or to automate lots of other processes, when your macro recorder is done, you will be able to edit it with any text editor, even the recordings can be manually edited.

When done your mouse macro recorder script can be extended so that when you record something the script puts in random parts or runs the playback faster, making it more time effective, it is also possible to make a recording loop over and over, that’s just some of the great things about learning how it works.

After reading this tutorial it’s my hope that you will know the procedure of writing a macro recorder and also know it’s really not all that complicated: You append your mouse moves and clicks to a variable, the tutorial recorder will not care about whatever game or application window is active only the mouse moves and clicks are recorded.

Obviously, you will need to make sure that you start recording from the initial state of the application or game, else your macro recording will probably not work the next time you start a playback.



The Top of the Script (the Auto-execute Section):

Start by making a new script file

Here at the top of the script you will put 3 lines that makes the script behave in a particular way

In the very first line you will set the script attribute #SingleInstance with the parameter force to force the script to replace the old instance automatically if/when it is already running. This is to make sure only one mouse macro recorder is running at a time.

#SingleInstance, force


Next line you will set SetBatchLines with a parameter of  -1  when you use -1 it makes the script never sleep between lines (i.e. have the script run at maximum speed).

SetBatchLines, -1


Last attribute will be CoordMode with two parameters, first will be Mouse and the second is Screen what this does is, it sets the coordinate mode for the mouse commands so they’re relative to the screen.

CoordMode, Mouse, Screen


The HotKeys that make the magic happen

Next you will define all the hotkeys (keyboard shortcuts) this will give you a way to start and stop the mouse macro recorder with the press of a button, but it is also a great way to let the recorder know what mouse button is pressed when.

So let start by setting up the keys/buttons we’d like to record, for this you will use the Hotkey command with two parameters, the first one will be the name of the hotkey like the left mouse button (i.e. LButton ) and the second parameter is the routine to call when this button is pressed.

For our recorder we will record the 4 main mouse buttons both their up and down event so that’s the left, right, middle plus the mouse wheel and you will need them to call a routine, for this tutorial I called the routine ClickHotkeys: . I will go over this routine with you later in this tutorial.

Hotkey, ~LButton, ClickHotkeys
Hotkey, ~LButton Up,ClickHotkeys
Hotkey, ~RButton, ClickHotkeys
Hotkey, ~RButton Up,ClickHotkeys
Hotkey, ~MButton, ClickHotkeys
Hotkey, ~MButton Up,ClickHotkeys
Hotkey, ~WheelDown, ClickHotkeys
Hotkey, ~WheelUp, ClickHotkeys


Now to the hotkeys that will control the mouse macro recorder script

Here you can use what ever keys you’d like, but for this tutorial, I have picked the r, s, p and o to do the 5 things this tutorial is made over and that’s r=record, s=stop/save, p=play and o=open

But to not have the script record, start or stop every time I press one of those letters, I have also used modifier keys (i.e. ^=Ctrl, +=shift, !=alt or #=win keys) .

The hotkey(s) you just setup, needs to do something and one way to do that is to use the GoSub command, what it does is it tells the script to go to a specific subroutine label in the script.

So that looks like this

^+r:: GoSub, Record
!+s:: GoSub, Save
^+s:: GoSub, Stop
^+p:: GoSub, Play
^+o:: GoSub, Open


That’s the end of the top of the script ( i.e Auto-execute section ) and you need to tell the script not to read/execute any more lines before you press one of the hotkeys you just setup, for this, we will use the return command



Time for subroutines, lets start with “ClickHotkeys”

Subroutines like the ones you will use in this tutorial all start with a label, the first one I have called ClickHotkeys: the colon at the end tells the script that this is a label, if you remember all the hotkeys you just setup above, all used this label name as their 3rd parameter.

For the sake of keeping an overview you can use curly brackets to show where the routine starts and ends but it’s not needed ( I use them for show in this tutorial script )



So now in this routine you will make the script first check the is_recording variable with an If statement to know if the script is recording now ( the variable is set in other routines, I will also go over this later in the tutorial ) the line below ( or the multiple lines inside the brackets ) of this statement will only execute if the variable is_recording is true.

if is_recording


Within this If statement ( block ) we now know that the script is recording, so you need to make the script save/store the button that was used, this you do with the := operator and the built-in function SubStr()  and the variable A_ThisHotkey when doing this you only want the used hotkeys name which start at the 2nd character within the variable so you need to remove the “~” from the front, it looks like this:

this_button := SubStr(A_ThisHotkey, 2)


Then an If statement using the “InStr()” function checks if the used hotkey has the string of characters ” Up” ( i.e. a space and the letters u and p ) in it.

if InStr(A_ThisHotkey, " Up")


If thats true ( i.e. it has the string ” Up” ) then you simply store a blank value in the variable called this_state so the routine does not add an extra ” Up” later.

this_state := ""


If A_ThisHotkey does not contain the string ” Up” the script will execute the else part of the If and you will know it’s a down event and need to fill this_state with the string ” Down” ( with a space at the front )  as that’s the event the recorder needs to store to later play it back.

    this_state := " Down"


After this you need to store the hotkey and its state in the recording variable, this is the variable that is currently holding all the recorded events.

For this you need to use the .= operator, this tells the script to append data to the variable (i.e. keep what’s already recorded and only add to it. ) and when you’re at it you can also close the is_recording block with a closing bracket.

    recording .= this_button .  this_state "."


That is all there is to the ClickHotkeys subroutine so now you just need to end the routine with a return ( and an extra closing bracket if you used one like me )



1/3 of the script is already done.

a 3nd of the mouse macro recorder code


Second subroutine will be “Record”

In this section I will help you learn how to make a routine that records all the mouse movements you make.

First you start with the routine label Record: ( again I will use an opening bracket )

Record: ; Start Recording


As line one in this routine you need to clear the variables used within this routine so that you are sure that they start out blank, this is done in a single line like this

Stored_X := Stored_Y := script := ""


Then just be sure you use the CoordMode command again to set the mouse coordinates as relative to the screen.

CoordMode, Mouse, Screen


Then you set the is_recording variable to true, so you can check it in other routines, to know if a recording is active

is_recording := true


Now its time for some visual feedback so you ( the user ) can see what the mouse macro recorder is doing and when, for this you will use the TrayTip with a text reading “Recording…” and lets set it to shown for 10.

TrayTip, MMR, Recording..., 10


TIP #1

Any recording you create will only work on the specific PC that you recorded it on. Things like changes in window size, resolution (dpi) or other Windows settings can make recorded scripts useless. So I would recommend that you select one PC or laptop that you use to do the auto clicking or automated tasks.


Now comes the main thing in this routine the loop

A while-loop specifically, a while loop will keep evaluating an expression repeatedly until the expression is false.

So you will use it to keep checking the is_recording variable and the script will loop (record) as long (while) as the recording state is true, and run the block ( {…} ) of code below it on each iteration.

while is_recording


In this while-loop block you now get the current position of the mouse cursor with the MouseGetPos command, and use the variable X and Y to store the coordinates in.

MouseGetPos, X, Y


Then you use an If statement to check if the coordinates (i.e. mouse position changed ) in the X , Y variables are the same as the last coordinates stored in the variables Stored_ X/Y at the end of this routine, looks like this

if (Stored_X=X and Stored_Y=Y)


If the coordinates have not changed this statement is true and you simply need to append ( using .= ) something to the recording variable recording that tells the playback routine to not move the mouse, the way I do it is by appending a simply + symbol, also note that every recorded step in the recording variable is delimited by a dot ( i.e. period)  this tells the playback routine where each field ( i.e. Step ) starts and stops.

recording .= "+."


Else the coordinates has changed and you now need to append ( .= ) this step to the recording variable like this

    recording .= X "," Y "."


And in this block you also need to store the current coordinates so you can use them to check if the mouse has moved in the next iteration of the loop and its also the last line of this else block so end it with a closing bracket

    Stored_X:=X, Stored_Y:=Y


Back out in the while-loop block, its a good idea to have the script wait before the next loop, just for a moment to save on the cpu use, this is done with the Sleep command which makes the script wait for a set amount of milliseconds, I use 10 as that’s about the smallest amount anyway, and remember the closing bracket to close the while-loop block

    Sleep, 10


TIP #2

The most important part when recording tasks is planning. You need to know exactly what you intend to do and also how to use the mouse to do it, before you press record. (ctrl+shift+r)


Now out of the while-loop means that the recording has come to an end and so has this routine, I found that it’s a good idea to clean up the end of the recording variable by extracting the last characters, you can do this using the “SubStr” function with a negative value in the 3rd parameter ( Length ) so that the variable does not have a blank last step ( i.e field ) when you play it back.

As it’s also the end of this routine it’s time for a return and the optional closing bracket

recording := SubStr(script, 1, -1) 


 That is about half of all there is to this tutorial and also the script


Recording part of the mouse macro recorder



“Open” will be the next subroutine

Lets go over how you make a subroutine to open any prior saved recordings.

Again you start with the label name followed by a colon ( + open bracket )

Open: ; Open Recording


Then in the context of this script its best to make sure that there is no active macro recording so you call the Stop routine using GoSub like this

GoSub, Stop


Now that you have stopped any recording its time to find the saved file, for this you can use the command FileSelectFile with one or more parameters this will open a file selection dialog box.

For this tutorial I’ve used all 5 parameters, first one is the name of the variable that will hold the path to the file that gets selected, the other parameters are Options, RootDir\Filename, Prompt, Filter , where Options and Filter are the one’s to really keep an eye on here, you will use the option 2 that is “Path Must Exist”, and in the filter parameter you will put the extension of your recording files in parentheses with a wildcard * ( i.e (*.mmr) )

FileSelectFile, OpenDir, 2, %A_ScriptDir%, Select File:, JSZ - Mouse Macro Recorder (*.mmr)


The ErrorLevel  variable will tell you if anything did not work or if the file dialog was canceled so lets check that with an If statement, to make sure there was no error with selecting a file

if Not ErrorLevel


In this If block you know that the user selected a file and the file path is in the variable OpenDir from the first parameter of the FileSelectFile command, this info you now use with the FileRead command to read the content of the selected file (i.e recording ) and store it in the recording variable for the playback routine or to extent an old recording, as this is a command you need to use % around the variable to tell the command to use the path in the variable and not the word OpenDir as the path, and that’s all their needs to go inside this If block so remember to close with a closing bracket

    FileRead, recording, %OpenDir%


 TIP #3

To perfect your macros and have them be most effective, you will have to experiment. This is not a cake recipe. When it comes to setting up moves and clicks, experience and planning is what will make the difference between a bad recording and a highly effective one. Mouse Recording allows for very complex tasks to be scripted, if used right.


That is the end of the Open routine as that is all there is to opening and reading a file, so time for the ending return and the still optional closing bracket



 That is how you make an “open” routine.

Mouse macro recorder open routine


Lets “Save” as this is the next routine

Here I will go over how you can make a Save routine for the mouse macro recorder, so that you can Save your recordings to use or playback later.

Label time, this routines name will be… Save, I think it’s a good name as that is what this routine does, I will again use an opening bracket, it’s up to you if you’re going to do the same

Save: ; Save Recording


This routine also needs any recording to stop before doing its thing, so again you need to use GoSub to the Stop label at the top of the stop routine, to stop the macro from recording if it is.

GoSub, Stop


For this routine you also need a file or a file name, at least to save the mouse recording to, so you will again use FileSelectFile just like in the Open routine above but this time you need to name the variable in the first parameter something else, I used the name SaveDir for the variable that will hold the path and name of the file to store the recorded data in

FileSelectFile, SaveDir, S2, %A_ScriptDir%, Save As:, JSZ - Mouse Macro Recorder (*.mmr)


You need to make sure there was no error, with selecting a place or name, using ErrorLevel just like in the last routine

if Not ErrorLevel


As this If block is for saving ( i.e Creating files ) you need to make sure that the file(s) can be found again, one way to do that is by giving your files an extension you know is a mouse macro recording.

I picked the extension “mmr” for mouse macro recorder but you can use something else if you like.

To make sure the filename ends with the extension you picked you can use RegEx, what I have done here is use RegExReplace to only remove “mmr” if the user typed it in, and always append it, to make sure there’s only one.

SaveDir := RegExReplace(SaveDir, "i)\.mmr") ".mmr"


Before making a new file for the recording you can use FileDelete with the SaveDir variable to delete any file with the selected name at that place.

FileDelete, %SaveDir%


Now you will need to use the FileAppend Command to create a new file with the data in the recording variable at the selected path and with the name in the variable SaveDir , also end this block with a closing bracket

FileAppend, %recording%, %SaveDir%


All saved now! Time to end the Save routine with a return and the closing bracket if you used one at the start of the routine



Saving Done! Only 35 lines of script to go before you’ve made a mouse macro recorder

Mouse macro recorder Save routine


Stop! Will be the routine we look at now

Lets see, this routine will be the one you use to stop the recording of the mouse moves and clicks and its also the routine that the other routines call (i.e. gosub) to make sure that recording is stopped before executing.

First write the label and bracket ( if you like ) so the script and the other routines knows where in the script to execute from when you press the stop hotkey or use the gosub command.

Stop: ; Stop Recording


Then you check the variable is_playing with an if statement and start the if block with an opening bracket

if is_playing


Then inside the “true block” you display a message with TrayTip telling the user that playback has stopped

TrayTip, MMR, Playback Stopped., 10


You need to set the is_playing variable to false so that the playback loop will stop as the while

is_playing := false


As playback is now turned off, you use a return to end the executing of this routine and return script execution to where it came from and then close this “true block” with a closing bracket



TIP #4

Remember to think about: What happens if my PC is slow? What happens if the browser does not load as fast? What happens if there is a prompt in a browser game? What happens if I get logged out automatically? – There are a lot of things to overcome, but a mouse macro recording can handle most of them without a problem.


As the is_playing if statement was not true, this part will execute meaning that the recorder is running, so set that to false to stop any recording

is_recording := false


Then show a message using TrayTip that tells the user that recording has been stopped

TrayTip, MMR, Recording Stopped., 10


That is all there is to the stop subroutine so end it with a return and a closing bracket if you opened the routine with one



Routine that will stop both playback or recording done! Just one routine to go and bingo.

Mouse macro recorder Stop routine

Déjà vu! No its just the “play” back routine

Start the Playback routine with a label call play and if you like an opening bracket



Start by clearing the variables used in this routine before starting playback

Stored_X := Stored_Y := ""


Now you set the is_playing variable to true so other routine will know that playback is running

is_playing := true


Use a TrayTip to tell the user that the playback has started

TrayTip, MMR, Playback Started., 10


Next you will use a parsing loop to make the script playback all the actions you recorded in the record routine, the loop will step through all the recorded actions (action parts) using the delimiter dot we used in the recording routine above

Loop, Parse, recording, .


Here you can start by making the script wait for the least amount of time to make the playback use less cpu power

Sleep, -1


Now you use an if statement to check that the is_playing variable is not true, if it’s not true, one of the other routines, has set it to false

if Not is_playing


If it’s not true aka false one of the other routines has made it so, to stop the playback loop



Else keep playing back the recordings next step, you can use RegExMatch to check the built-in parsing loop variable A_LoopField and that way know if the current action part has two sets of digits, and store them in the variables point1 and  point2 , also using an opening bracket to start a block for when this if is true (i.e two sets of digits are found)

else if RegExMatch(A_LoopField,"(\d+),(\d+)", point)



In this black you know that the action is a mouse move, so use the MouseMove command to move the mouse pointer to the coordinates in the two point variables

MouseMove, %point1%, %point2%, 0


End this If block by storing the last used points (i.e points1 and 2 ) in the two stored _X and stored_Y variables like this and close the block with a bracket

Stored_X:=point1, Stored_Y:=point2


after that you use an else if to check if the current parsed action part has a + symbol

else if (A_LoopField = "+")


If it had a + symbol use MouseMove to move the mouse pointer to the last used coordinates at a speed of zero (i.e normal speed)

MouseMove, %Stored_X%, %Stored_Y%, 0


Last you use an else , because the only option left for the action part is to contain a button press



So you use send to send the recorded button press, i.e the text contained in the parsing loops A_LoopField variable like this and you also end the parsing loop with a closing bracket

    Send, {%A_LoopField%}


Now all the action parts have been looped over or the loop has been stop by another sub-routine, but you still need to set the is_playing variable to false so the rest of the script knows that playback is not running

is_playing := false


At this time its nice if you also show a TrayTip telling the user that the playback is over.

TrayTip, MMR, Playback Done., 10


Then all theres left for you to do is to end this routine with a return and the optional bracket



Mouse macro recorder Play routine



That is all, Now you have a fully working mouse macro recorder, of course there are many ways to do this and I’d be glad to cover them in later tutorials if you wish? Please tell me what other macro recorder questions you have or like me to answer things like making a keyboard macro program.

If you have any questions or ways that you use to record or automate actions, please feel free to use the comments or contact page and tell me all about it.


Try it:

To use your new script, continue as follows: 

  • Write or Copy all the line above and then Save the file as .ahk and close the file.
  • Double-click the file to launch it. A new icon appears in the taskbar notification area.
  • Some scripts may need you to press a Hotkey or Hotstring to see the script in action
  • To exit or edit the script, right-click the green “H” icon in the taskbar notification area. (and click the exit option)



AutoHotkey Scripts like this can easily do lots of other things, I have shown you very little in this tutorial.

You can also have many scripts running simultaneously, each with its own icon in the taskbar notification area all doing their tasks automatically.

To have this script start automatically when you start your computer, create a shortcut to the script file in the Start Menu’s Startup folder.



Script (.ahk)  

Free – Get



Application (.exe) 

Free – Get





  1. could u plz send me the above script in its totality so I dont have to copy line-by-line from this web page. I’ve tried the download link [“Script (.ahk)”] on this page to no avail. Beautiful article, I hope that u will be rewarded for ur generosity some how, some day.
    sincerily jashauh

  2. Ok so this is working great but when i play it back it doesnt click

  3. ah great thx for the link, will read up on that!

    I read some about AHK and if it dosent respond it might need delay inbetween actions like capslook click.

    send {capslock down}
    sleep 25
    send {capslock UP}

    without the sleep its to fast for the game to recognize the click.

  4. Hi jsz!
    thx for a great script! Tho I have a problem with it, im trying to get it to work with a RPG game thats made in Unity and the script dosent work ingame, works fine in windows ect.

    and one more think how to I add a sleep in the click like:

    Hotkey, ~LButton, ClickHotkeys
    sleep 25
    Hotkey, ~LButton Up,ClickHotkeys

    I know its not done like that but best way to try to explain.

    1. When script don’t work in game there a lot of things that may be the source of the issue

      This topic list some things to try

      One thing to try first is to make sure that your script is run with as high or higher privileges than your game aka Admin

      On the sleep thing, I’m not really sure what you’re asking for do you wish for the script to hold the button down for longer than you recorded?


  5. Thanks this is excellent! Any tips on adding keyboard recording capabilities to this script ?

    1. Thank you, glad you like it…

      Tips will depend a lot on your need:

        Very simple way is to just add all the keys you wish to record as hotkeys in the top of the script.

        Hotkey, ~q,		ClickHotkeys
        Hotkey, ~q Up,		ClickHotkeys
        Hotkey, ~w,		ClickHotkeys
        Hotkey, ~w Up,		ClickHotkeys
        Hotkey, ~e,		ClickHotkeys
        Hotkey, ~e Up,		ClickHotkeys

        This is a very simple way to do it and it may be all that you need,

        but it will not work for all keyboard keys as some keys need special handling.

        Things like the modifiers are also not taken in to account…

        If you really wish!
        You can used a keyboard hook like in this script

      Hope it helps

  6. Awesome! 😀

    But I have trouble for my own purposes!

    The record routine, also saves the times between the clicks.. I want to remove it or put a predefined time to every click, for example 200 miliseconds how to do it?

    1. Hi Alex,

      Great you like it!

      There is more than one way to do what you’re asking for 🙂

      1) To not record any pause between clicks you can replace line 56

      recording .= "+."



      1.1) You can also use RegExReplace to remove all the + symbols from a loaded recording

      New_Recording := RegExReplace(recording, "(\+\.)+", "")

      2) To put a predefined time between clicks will take a little more work

      again using RegEx to replace multiple + symbols with a single one like this

      New_Recording := RegExReplace(recording, "(\+\.)+", "+.")

      And then in the Playback routine replace line 123 and 124 with

      else if (A_LoopField = "+")
      	    sleep 200

      I hope that helps you do what you need…

      1. Thank you! Now works!

        But I have some questions about recording & play ..
        I’m using this for a game, so save & open are useless for the thing I want to do.

        Recording routine records the mouse positions too, how to make it for only records the clicks? For example I need to make a hell route to click some item, so I like to just click the item instead of follow the route of the mouse I recorded.

        How to put a stop for record when I play the recorded thing? and how to make a hotkey to delete all recorded data, for start over?

        Also, how to put play routine to loop infinite until I press some key then stop it?

        Sorry for all questions!! I’m a newbie on autohotkey!

        1. Hey again Alex

          Happy its working for you.

          I think that your questions are a little bit too specific, to your need, at least for me to make a lengthy replay here in the comments…

          What I’ll ask you to do is use the contact page ( link at the top of the page ) or send me an email at

          And I’ll be happy to hear more about your project and see if I can help you out.

          1. Already send you an email via contact form!

            Thank you for your time!!

  7. Hi Jackie, I got the message” Mouse macro recorder tutorial script, No downloadable files found.” when I tried to checkout. Then I received an email with a link for download but the link only start your home page. Any idea?

    1. Hi Denis

      Thank you for reporting, it was a simple credentials error, sorry but that.

      Please try again

Leave a Reply