Scripting Language

Table of Contents

General Conventions

Names: Variable and function names are not case sensitive (for example, CurrentDate is the same as currentdate). For details such as maximum length and usable characters, see Names.

  • Function and method calls require there to be no space between the function/method name and (.
  • Spaces are required when performing concatenation.
  • Spaces may be required between two operators, to remove ambiguity.
  • Single-line comments require a leading space if they are not at the start of the line.
  • Line continuation, where lines that begin with an expression operator (except ++ and — ) are merged with the previous line. Lines are merged regardless of whether the line actually contains an expression.
  • Continuation sections, where multiple lines are merged with the line above the section. The start and end of a continuation section are marked with ( and ) (both symbols must appear at the beginning of a line, excluding whitespace).
; This entire line is a comment.
Run Notepad; This is a comment on the same line as a command.
/* MsgBox, This line is commented out (disabled). MsgBox, Common mistake: */ this does not end the comment. MsgBox, This line is commented out. */


Expressions are combinations of one or more values, variables, operators and function calls. For example, 10, 1+1 and MyVar are valid expressions. Usually, an expression takes one or more values as input, performs one or more operations, and produces a value as the result. The process of finding out the value of an expression is called evaluation. For example, the expression 1+1 evaluates to the number 2.

Strings / Text

For a more general explanation of strings, see Strings.


For a basic explanation and general details about variables, see Variables.

  • Implicit concatenation: "The value is " MyVar
  • Explicit concatenation: "The value is " . MyVar
MsgBox % Format("You are using AutoHotkey v{1} {2}-bit.", A_AhkVersion, A_PtrSize*8)


Operators take the form of a symbol or group of symbols such as + or :=, or one of the words and, or, not or new. They take one, two or three values as input and return a value as the result. A value or sub-expression used as input for an operator is called an operand.

  • Unary operators are written either before or after a single operand, depending on the operator. For example, -x or not keyIsDown.
  • Binary operators are written in between their two operands. For example, 1+1 or 2 * 5.
  • AutoHotkey has only one ternary operator, which takes the form condition ? valueIfTrue : valueIfFalse.

Function Calls

For a general explanation of functions and related terminology, see Functions/Commands.

Operators for Objects

There are other symbols used in expressions which don’t quite fit into any of the categories defined above, or that affect the meaning of other parts of the expression, as described below. These all relate to objects in some way. Providing a full explanation of what each construct does would require introducing more concepts which are outside the scope of this section.

Expression Statements

Not all expressions can be used alone on a line. For example, a line consisting of just 21*2 or "Some text" wouldn't make any sense. An expression statement is an expression used on its own, typically for its side-effects. Most expressions with side-effects can be used this way, so it is generally not necessary to memorise the details of this section.

Legacy Syntax

Legacy or command syntax generally only allows a single action per line, but uses fewer characters to perform simple tasks such as sending keystrokes or running a program. The syntax consists of command and variable names, unquoted text and a few symbols such as ,, = and %.

  • %: Enclose a variable name in percent signs to include the contents of that variable. For example, The year is %A_Year%.
  • Note: Variable names are not always enclosed in percent signs; they are required only within unquoted text. Percent signs should not be used anywhere else, except to create a dynamic variable reference or dynamic function call.
  • Note: Only a plain variable name can be used. Array elements, properties and other expressions are not supported.
  • ,: Comma is used to delimit (separate) the parameters of a command, with some exceptions. It has no special meaning when used in an assignment or comparison, so is interpreted literally in such cases.
  • `: An escape character is usually used to indicate that the character immediately following it should be interpreted differently than it normally would. For example, `% produces a literal percent sign and `, produces a literal comma. Some other common escape sequences produce special characters, such as `t (tab), `n (linefeed), and `r (carriage return).
Send, The time is %A_Hour% o'clock.
Clipboard = This text is copied to the clipboard.
If Var = Text value


A command is an instruction to carry out a specific predefined action. “Command” may also refer to a specific predefined action, such as MsgBox. The set of available commands is predefined and cannot be changed by the script.

MsgBox, The time is %A_Hour% o'clock.

OutputVar and InputVar Parameters

OutputVar and InputVar parameters require a variable name or dynamic variable reference. For example:

; Replace all spaces with pluses: StringReplace, NewStr, OldStr, %A_Space%, +, All

Text Parameters

Text parameters accept unquoted text. For example:

MsgBox, The time is %A_Hour% o'clock.
  • In the last parameter of any command.
  • In the Text parameter of MsgBox, which has smart comma handling.

Numeric Parameters

Numeric parameters accept a literal number or an expression, and can be identified by phrasing like “This parameter can be an expression.”

Sleep %n%000; Sleep for n seconds. Sleep %m%; Sleep for m milliseconds.

% Expression

Although purely numeric parameters accept an expression by default, all other parameters of commands do not. Specify a percent sign followed by a space or tab to force a parameter to accept an expression. For example, all of the following are effectively identical because Sleep’s first parameter is expression-capable:

Sleep MillisecondsToWait Sleep %MillisecondsToWait% Sleep % MillisecondsToWait
  • The Var parameter of any legacy If command. Users can avoid confusion by always using if (expression).
  • OutputVar parameters, which accept a variable reference using the same syntax as expressions.

Documentation Conventions

At the top of each page which documents a command, there is usually a block showing syntax, like this:

StringLower, OutputVar, InputVar , T

Optional Parameters

Optional parameters can simply be left blank. The comma preceding an optional parameter can also be omitted if all subsequent parameters are omitted. For example, the Run command can accept between one and four parameters. All of the following are valid:

Run, notepad.exe, C:\ Run, notepad.exe,, Min Run notepad.exe, , , notepadPID

Expressions vs Legacy Syntax

Many command parameters do not accept expressions by default. Use the percent-space prefix at the beginning of a parameter to evaluate that parameter as an expression. In the following examples, the expression is shown on the first line (beginning after the percent sign), with pure legacy syntax shown on the second line.

MsgBox % 1+1; Shows "2" MsgBox 1+1; Shows "1+1"
MsgBox % "This is text." MsgBox This is text.
MsgBox % A_AhkVersion MsgBox %A_AhkVersion%
MsgBox % "Hello %A_UserName%."; Shows "%A_UserName%" MsgBox Hello %A_UserName%.; Shows your username.
MsgBox % "Hello " . A_UserName . "."; Shows your username.
MsgBox % Format("Hello {1}.", A_UserName); {} also works in place of {1}.
MyVar := "This is text." MyVar = This is text.if (Var1 = Var2) if Var1 = %Var2%
if (Var1 >= Low and Var1 <= High) if Var1 between %Low% and %High%

Different Equals

One common mistake is to write = where := is needed. For example:

Total = A + B; Assigns the literal text "A + B"

Commands vs Functions

In AutoHotkey v1, it is currently not possible to call a command from an expression, or to call a function using the command syntax. However, several commands have a function replacement.

Control Flow Statements

For a general explanation of control flow, see Control Flow.

  • A block (denoted by a pair of braces) groups zero or more statements to act as a single statement.
  • An If statement causes its body to be executed or not depending on a condition. It can be followed by an Else statement, which executes only if the condition was not met.
  • Goto jumps to the specified label and continues execution.
  • Gosub calls a subroutine.
  • Return returns from a subroutine or function.
  • A Loop statement (Loop, While or For) executes its body repeatedly.
  • Break exits (terminates) a loop.
  • Continue skips the rest of the current loop iteration and begins a new one.
  • Until causes a loop to terminate when an expression evaluates to true. The expression is evaluated after each iteration.
  • Switch executes one case from a list of mutually exclusive candidates.
  • Exception handling:
  • Try guards its body against runtime errors and exceptions thrown by the throw command.
  • Catch executes its body after an exception is thrown within a try statement (and only if an exception is thrown).
  • Finally executes its body when control is being transferred out of a try or catch statement’s body.
  • Throw throws an exception to be handled by try/catch or display an error dialog.

Control Flow vs Commands

Control flow statements have syntax resembling commands, and are often referred to as such, but some differ from commands:

  • There are several types of If statement, with each having different syntax.
  • For and several types of If statement use keywords or an operator instead of commas to separate some of their parameters.
  • The opening brace of a block can be written at the end of the same line as an If (expression), Else, Loop Count, While, For, Try, Catch or Finally statement (basically any control flow statement which does not use legacy syntax). This is referred to as the One True Brace (OTB) style. It is not supported by the other Loop sub-commands or legacy If statement, as the brace would be interpreted as a literal { character.
  • Else, Try and Finally allow any valid statement to their right, as they require a body but have no parameters.
  • If (expression) and While allow an open parenthesis to be used immediately after the name. For example, if(expression).
  • For, While, Until and Throw always accept expressions. They treat %var%, %var%000 and similar as expressions, whereas numeric parameters of other commands do not. The requirement for backward-compatibility does not apply to these control flow statements as they are relatively new.

If Statement

If (expression) evaluates an expression and executes the following statement only if the result is true.

  • Variable names must be enclosed in percent signs only on the right-hand side of the operator.
  • between, in, contains and is are only valid in this context; they cannot be used in expressions.
  • Multiple conditions cannot be written on the same line (such as with the and operator).
  • None of the parameters are expressions.

Loop Statement

There are several types of loop statements:

  • Loop Count executes a statement repeatedly: either the specified number of times or until break is encountered.
  • Loop Reg retrieves the contents of the specified registry subkey, one item at a time.
  • Loop Files retrieves the specified files or folders, one at a time.
  • Loop Parse retrieves substrings (fields) from a string, one at a time.
  • Loop Read retrieves the lines in a text file, one at a time.
  • While executes a statement repeatedly until the specified expression evaluates to false. The expression is evaluated before each iteration.
  • For executes a statement once for each value or pair of values returned by an enumerator, such as each key-value pair in an object.
t := "column 1`tcolumn 2`nvalue 1`tvalue 2" Loop Parse, t, `n { rowtext := A_LoopField rownum := A_Index; Save this for use in the second loop, below. Loop Parse, rowtext, `t { MsgBox %rownum%:%A_Index% = %A_LoopField% } }

Not Control Flow

As directives, labels (including hotkeys and hotstrings), and declarations without assignments are processed when the script is loaded from file, they are not subject to control flow. In other words, they take effect unconditionally, before the script ever executes any control flow statements. Similarly, the #If directives such as #IfWinActive cannot affect control flow; they merely set the criteria for any hotkey labels and hotstrings specified in the code. A hotkey’s criteria is evaluated each time it is pressed, not when the #If directive is encountered in the code.

Structure of a Script

Auto-execute Section

After the script has been loaded, it begins executing at the top line, continuing until a Return, Exit, the script’s first hotkey/hotstring label, or the physical end of the script is encountered (whichever comes first). This top portion of the script is referred to as the auto-execute section, but it is really just a subroutine which is called after program startup.


A subroutine (or sub) is a reusable block of code which can be called to perform some task.

gosub Label1 Label1: MsgBox %A_ThisLabel% return

User-Defined Functions

Generally speaking, a function is a kind of subroutine. However, within the AutoHotkey documentation, “subroutine” typically refers to the kind of subroutine defined by a label (described above).

MyFunction(FirstParameter, Second, ByRef Third, Fourth:="") { ... return "a value" }


The #Include directive causes the script to behave as though the specified file’s contents are present at this exact position. This is often used to organise code into separate files, or to make use of script libraries written by other users.

  • #Include generally should not be used in the middle of a subroutine or function.
  • The use of #Include in the script’s auto-execute section requires special consideration, because the auto-execute section is essentially just a subroutine. Execution of a subroutine halts if it reaches a return, regardless of which file that return is in. Similarly, if the file contains a hotkey/hotstring, it may be considered the script's first hotkey/hotstring, which would act like return.
  • The script only has one auto-execute section, not one per file.


Dynamic Variables

A dynamic variable reference takes a text value and interprets it as the name of a variable.

target := 42 second := "target" MsgBox %second%; Normal (single) variable reference in text => target MsgBox % second; Normal (single) variable reference in an expression => target MsgBox % %second%; Double-deref in an expression => 42
  • MsgBox %second%MsgBox target: Shows "target".
  • MsgBox % %second%MsgBox % target: Shows the contents of target, i.e. "42".


A pseudo-array is actually just a bunch of discrete variables, but with a naming pattern which allows them to be used like elements of an array. For example:

MyArray1 = A MyArray2 = B MyArray3 = C Loop 3 MsgBox % MyArray%A_Index%; Shows A, then B, then C.

Associative pseudo-arrays

The “index” used to form the final variable name does not have to be numeric; it could instead be a letter or keyword, making the pseudo-array similar to an associative array or an object. The following example creates a pseudo-array with elements “Left”, “Top”, “Right” and “Bottom”:

SysGet, WA, MonitorWorkArea MsgBox, Left: %WALeft% -- Top: %WATop% -- Right: %WARight% -- Bottom: %WABottom%.

Commands which create pseudo-arrays

There are several commands which create associative pseudo-arrays:


A label identifies a line of code, and can be used as a Goto target or to form a subroutine. There are three kinds of label: normal named labels, hotkey labels and hotstring labels.

  • A hotkey label can be directly followed by a command or other statement to create a one-line hotkey. In other words, if a command, assignment or expression is present on the same line as a hotkey label, it acts as though followed by return.
  • A hotkey with a key name written to the right of the double-colon is actually a , which is shorthand for a pair of hotkeys. For example, a::b creates hotkeys and labels for *a and *a Up, and does not create a label named a.
  • A hotstring with text written to the right of the final double-colon is an auto-replace hotstring. Auto-replace hotstrings do not act as labels.



Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store