- Home Board index AutoHotkey Scripts and Functions
- Search
-
- It is currently 23 Jan 2021, 09:30
- All times are UTC-05:00
Youtube to MP3
Post your working scripts, libraries and tools
-
- Posts: 713
- Joined: 21 Dec 2015, 02:34
Re: Youtube to MP3
Unfortunately not, only IE support automation like thisscriptor2016 wrote:can this be modified to work with Google Chrome?
- Delta Pythagorean
- Posts: 573
- Joined: 13 Feb 2017, 13:44
- GitHub: DelPyth
- Location: Somewhere in the US
Re: Youtube to MP3
Improved and easier to work with!
- Now Supports MP3 and MP4!
Full Code
Code: Select all
/*
=========================================================================
Title: YouTube Song and Video Downloader
=========================================================================
Descrition: Download your favorite videos and songs
at the push of a button... or two.
-------------------------------------------------------------------------
AutoHotkey Version: 1.1.26.01
Language: English
Used Platform(s): Win 10
Author: Delta Pythagorean
Contact information: [email protected]
|=======================================================================|
| Hotkeys: |
| None |
|=======================================================================|
=========================================================================
*/
#NoEnv
#SingleInstance Force
Process, Priority,, H
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
SetDefaultMouseSpeed, 0
SendMode, Input
CoordMode, Mouse, Screen
SetWorkingDir, %A_ScriptDir%
; Loads "downloader" to use.
pwb := ComObjCreate("InternetExplorer.Application")
pwb.Visible := False
pwb.Navigate("https://ytmp3.cc/")
While (pwb.busy) || (pwb.ReadyState != 4)
Sleep, 10
Info :=
(LTrim
"YouTube Video and Song downloader.
Version: 1.0.0
<a href=""https://autohotkey.com/boards/viewtopic.php?f=6&t=39623&p=182816#p182816"">Current Version</a> by: Delta Pythagorean
<a href=""https://autohotkey.com/boards/viewtopic.php?f=6&t=39623"">Original Version</a> by: HIAC"
)
; You'll see what I mean by these later...
Items := {MP3: "Song", MP4: "Video"}
Names := {MP3: "mp3", MP4: "mp4", Song: "Song File", Video: "Video File"}
Menu, Tray, Icon, Shell32.dll, 123
Menu, Tray, NoStandard
Menu, Download, Add, MP3 File, MP3File
Menu, Download, Add, MP4 File, MP4File
Menu, Tray, Add, Download To..., :Download
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitApp
OnExit, ExitApp
If (FileExist(DataFile := A_ScriptDir "\config.cfg")) {
Data := JSON.Load(FileOpen(DataFile, "r").Read())
ItemType := Data.Data
Check%ItemType% := "Checked"
} Else
CheckMP3 := "Checked"
Quote := """"
Gui, -MinimizeBox
Gui, Color, White
Gui, Add, Pic, x5 y5 w60 h60 Icon123, % "Shell32.dll"
Gui, Font, s9
Gui, Add, Link, x70 y10 w305 h85 -TabStop, % Info
Gui, Font, s8
Gui, Add, Edit, x5 y100 w340 h20 vURL hwndURL -TabStop, % Data.Url
SendMessage, 0x1501, True, "http://",, ahk_id %URL%
Gui, Add, Button, x345 y100 h21 w35 hwndLinkIn -TabStop gPaste
GuiButtonIcon(LinkIn, A_WinDir "\System32\Shell32.dll", 134, "a5 s27")
Gui, Add, Radio, x5 y130 w100 h20 vMP3 %CheckMP3% -TabStop, Download MP3
Gui, Add, Radio, x5 y150 w100 h20 vMP4 %CheckMP4% -TabStop, Download MP4
Gui, Add, Text, x0 y125 w380 h2 +0x10
Gui, Add, Button, x225 y180 w75 h23 Default, OK
Gui, Add, Button, x305 y180 w75 h23, Close
Gui, Add, Progress, x-5 y205 w390 h25 vDProgress -Smooth, 0
Gui, Add, StatusBar, x0 y211 w569 h23, Waiting on user input...
Gui, Show, w382 h254, YouTube Downloader
; Adds System Menu Items to GUI
; DO NOT EDIT -------------------------------------------------------------------------------------------
hSysMenu := DllCall("GetSystemMenu", "UInt", WinExist("A"), "Int", False)
DllCall("AppendMenu", "Ptr", hSysMenu, "UInt", 0x800, "UInt", 0, "Str", "") ; Separator
DllCall("AppendMenu", "Ptr", hSysMenu, "UInt", 0, "UPtr", 0xDEAD, "Str", "Download MP3")
DllCall("AppendMenu", "Ptr", hSysMenu, "UInt", 0, "UPtr", 0xC0DE, "Str", "Download MP4")
OnMessage(0x112, "OnWM_COMMAND")
OnMessage(0x211, "OnWM_ENTERMENULOOP")
Return
Paste:
GuiControl,, Url, % RegExReplace(Clipboard, "\&{1}.+$")
ShowBalloonTip(URl, "", "You may now download the video or song if you'd like.")
Return
ButtonClose:
GuiClose:
ExitApp:
Gui, Submit, NoHide
Type := MP3 ? "MP3" : "MP4"
If (!FileExist(DataFile))
FileAppend, % JSON.Dump({Data: Type, Url: Url}), % DataFile
Else {
FileDelete, % DataFile
FileAppend, % JSON.Dump({Data: Type, Url: Url}), % DataFile
}
pwb.quit()
ExitApp
Return
ButtonOK:
MP3File:
MP4File:
Gui, Submit, NoHide
If (URL ~= "^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/watch\?v=([^&]+)") {
If (IsObject(pwb)) {
GuiControl, Disable, URL
GuiControl, Disable, OK
SB_SetText("Preparing Download...")
GuiControl,, DProgress, 10
pwb.document.getElementById("input").value := URL
Type := MP3 ? "MP3" : "MP4"
If (Type = "MP3") || (A_ThisFunc = "MP3File")
pwb.document.getElementById("mp3").click(), Type := "MP3"
Else If (Type = "MP4") || (A_ThisFunc = "MP3File")
pwb.document.getElementById("mp4").click(), Type := "MP4"
pwb.document.getElementById("submit").click()
Gui, +OwnDialogs
While ((Inprogress := pwb.document.getElementById("file").href) = "https://ytmp3.cc/") {
If ((pwb.document.getElementById("progress").innertext) = "checking video ") {
SB_SetText("Checking the " Items[Type] "...")
GuiControl,, DProgress, 20
} Else if ((pwb.document.getElementById("progress").innertext) = "loading video ") {
SB_SetText("Loading " Items[Type] "...")
GuiControl,, DProgress, 30
} Else if ((pwb.document.getElementById("progress").innertext) = "converting video ") {
SB_SetText("Converting " Items[Type] "...")
GuiControl,, DProgress, 40
}
Sleep, 100
}
GuiControl,, DProgress, 50
DirectUrl := pwb.document.getElementById("file").href
GuiControl,, DProgress, 70
FileSelectFile, File, S8,,, % Names[Items[Type]] " (*." Names[Type] ")"
If (ErrorLevel) {
TrayTip,, % "File not Selected, giving random name..."
File := A_Desktop "\" Names[Items[Type]] " - " A_NowUTC "." Items[Type]
} Else
If (!RegExMatch(File, "\.(mp3|mp4)$"))
File := File "." StrLower(Names[Type])
SB_SetText("Downloading, please wait...")
DownloadFile(DirectUrl, File)
SB_SetText("Download successful!")
GuiControl,, DProgress, 100
GuiControl,, URL
GuiControl, Enable, URL
GuiControl, Enable, OK
} Else {
MsgBox, 16, % "Error", % "Failed to connect. Retrying..."
Reload
; Precaution if program doesn't reload
MsgBox, 16, % "Error", % "Could not reload the program. Closing down...", 3
ExitApp
}
} Else {
SB_SetText("Invalid URL")
GuiControl,,URL
GuiControl, Focus, URL
}
Sleep, 100
GuiControl,, DProgress, 0
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xDEAD, "UInt", True)
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xC0DE, "UInt", True)
SB_SetText("Waiting on user input...")
Return
StrLower(ByRef Out, Opt := "") {
StringLower, Out, Out, % Opt.Title ? "T" : ""
If (!IsByref(Out))
Return, Out
}
DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) {
;Check if the file already exists and if we must not overwrite it
If (!Overwrite && FileExist(SaveFileAs))
Return
;Check if the user wants a progressbar
If (UseProgressBar) {
;Initialize the WinHttpRequest Object
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
;Download the headers
WebRequest.Open("HEAD", UrlToFile)
WebRequest.Send()
;Store the header which holds the file size in a variable:
FinalSize := WebRequest.GetResponseHeader("Content-Length")
;Create the progressbar and the timer
Progress, M H80,, Downloading..., %UrlToFile%
SetTimer, __UpdateProgressBar__, 100
}
;Download the file
UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
;Remove the timer and the progressbar because the download has finished
If (UseProgressBar) {
Progress, Off
SetTimer, __UpdateProgressBar__, Off
}
Return
;The label that updates the progressbar
__UpdateProgressBar__:
FileName := SplitPath(SaveFileAs).NameNoExt
;Get the current filesize and tick
CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
CurrentSizeTick := A_TickCount
;Calculate the downloadspeed
Speed := (Amount := Round((CurrentSize / 1024 - LastSize / 1024) / ((CurrentSizeTick - LastSizeTick) / 1000))) > 1024 ? Amount " KB/s" : Round(Amount, 0) " MB/s"
;Save the current filesize and tick for the next time
LastSizeTick := CurrentSizeTick
LastSize := FileOpen(SaveFileAs, "r").Length
;Calculate percent done
PercentDone := Round(CurrentSize / FinalSize * 100)
;Update the ProgressBar
Progress, %PercentDone%, %PercentDone%`% Done, Downloading... (%Speed%), Downloading %FileName% (%PercentDone%`%)
Return
}
GuiButtonIcon(Handle, File := "%A_WinDir%\System32\Shell32.dll", Index := 1, Options := "s26 a5 r1 t1") {
RegExMatch(Options, "i)w\K\d+", W), (W="") ? W := 16 :
RegExMatch(Options, "i)h\K\d+", H), (H="") ? H := 16 :
RegExMatch(Options, "i)s\K\d+", S), S ? W := H := S :
RegExMatch(Options, "i)l\K\d+", L), (L="") ? L := 0 :
RegExMatch(Options, "i)t\K\d+", T), (T="") ? T := 0 :
RegExMatch(Options, "i)r\K\d+", R), (R="") ? R := 0 :
RegExMatch(Options, "i)b\K\d+", B), (B="") ? B := 0 :
RegExMatch(Options, "i)a\K\d+", A), (A="") ? A := 4 :
Psz := A_PtrSize = "" ? 4 : A_PtrSize, DW := "UInt", Ptr := A_PtrSize = "" ? DW : "Ptr"
VarSetCapacity( button_il, 20 + Psz, 0 )
NumPut( normal_il := DllCall( "ImageList_Create", DW, W, DW, H, DW, 0x21, DW, 1, DW, 1 ), button_il, 0, Ptr ) ; Width & Height
NumPut( L, button_il, 0 + Psz, DW ) ; Left Margin
NumPut( T, button_il, 4 + Psz, DW ) ; Top Margin
NumPut( R, button_il, 8 + Psz, DW ) ; Right Margin
NumPut( B, button_il, 12 + Psz, DW ) ; Bottom Margin
NumPut( A, button_il, 16 + Psz, DW ) ; Alignment
SendMessage, BCM_SETIMAGELIST := 5634, 0, &button_il,, AHK_ID %Handle%
Return IL_Add(normal_il, File, Index)
}
SplitPath(File) {
SplitPath, File, F, D, E, N, D_
Return, {FileName: F, Dir: D, Ext: E, NameNoExt: N, Drive: D_}
}
ShowBalloonTip(hEdit, Title, Text, Icon := 0) {
NumPut(VarSetCapacity(EDITBALLOONTIP, 4 * A_PtrSize, 0), EDITBALLOONTIP)
NumPut(&Title, EDITBALLOONTIP, A_PtrSize, "Ptr")
NumPut(&Text, EDITBALLOONTIP, A_PtrSize * 2, "Ptr")
NumPut(Icon, EDITBALLOONTIP, A_PtrSize * 3, "UInt")
SendMessage 0x1503, 0, &EDITBALLOONTIP,, ahk_id %hEdit% ; EM_SHOWBALLOONTIP
Return ErrorLevel
}
; Enable/disable system menu items
OnWM_ENTERMENULOOP(wParam, lParam, msg, hWnd) {
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xDEAD, "UInt", True)
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xC0DE, "UInt", True)
}
; System menu handler
OnWM_COMMAND(wParam, lParam, msg, hWnd) {
Global
If (wParam == 0xDEAD) {
GoSub, MP3File
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xDEAD, "UInt", False)
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xC0DE, "UInt", False)
} Else If (wParam == 0xC0DE) {
GoSub, MP4File
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xDEAD, "UInt", False)
DllCall("EnableMenuItem", "Ptr", hSysMenu, "UPtr", 0xC0DE, "UInt", False)
}
}
/*
================================================================
DO NOT MESS WITH ANYTHING BELOW THIS LINE
THIS IS FOR THE PROGRAM TO READ AND USE DATA FROM FILES
================================================================
*/
class JSON {
class Load extends JSON.Functor {
Call(self, ByRef text, reviver:="") {
this.rev := IsObject(reviver) ? reviver : false
; Object keys(and array indices) are temporarily stored in arrays so that
; we can enumerate them in the order they appear in the document/text instead
; of alphabetically. Skip if no reviver function is specified.
this.keys := this.rev ? {} : false
static quot := Chr(34), bashq := "\" quot
, json_value := quot . "{[01234567890-tfn"
, json_value_or_array_closing := quot "{[]01234567890-tfn"
, object_key_or_object_closing := quot "}"
key := ""
is_key := false
root := {}
stack := [root]
next := json_value
pos := 0
text := RegExReplace(text, "m)((?:\s+|)\/\/.*)$") ; Removes all comments
while ((ch := SubStr(text, ++pos, 1)) != "") {
if InStr(" `t`r`n", ch)
continue
if !InStr(next, ch, 1)
this.ParseError(next, text, pos)
holder := stack[1]
is_array := holder.IsArray
if InStr(",:", ch) {
next := (is_key := !is_array && ch == ",") ? quot : json_value
} else if InStr("}]", ch) {
ObjRemoveAt(stack, 1)
next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"
} else {
if InStr("{[", ch) {
; Check if Array() is overridden and if its return value has
; the 'IsArray' property. If so, Array() will be called normally,
; otherwise, use a custom base object for arrays
static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
; sacrifice readability for minor(actually negligible) performance gain
(ch == "{")
? ( is_key := true
, value := {}
, next := object_key_or_object_closing )
; ch == "["
: ( value := json_array ? new json_array : []
, next := json_value_or_array_closing )
ObjInsertAt(stack, 1, value)
if (this.keys)
this.keys[value] := []
} else {
if (ch == quot) {
i := pos
while (i := InStr(text, quot,, i+1)) {
value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")
static tail := A_AhkVersion<"2" ? 0 : -1
if (SubStr(value, tail) != "\")
break
}
if (!i)
this.ParseError("'", text, pos)
value := StrReplace(value, "\/", "/")
, value := StrReplace(value, bashq, quot)
, value := StrReplace(value, "\b", "`b")
, value := StrReplace(value, "\f", "`f")
, value := StrReplace(value, "\n", "`n")
, value := StrReplace(value, "\r", "`r")
, value := StrReplace(value, "\t", "`t")
pos := i ; update pos
i := 0
while (i := InStr(value, "\",, i+1)) {
if !(SubStr(value, i+1, 1) == "u")
this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))
uffff := Abs("0x" . SubStr(value, i+2, 4))
if (A_IsUnicode || uffff < 0x100)
value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
}
if (is_key) {
key := value, next := ":"
continue
}
} else {
value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)
static number := "number", integer :="integer"
if value is %number%
{
if value is %integer%
value += 0
}
else if (value == "true" || value == "false")
value := %value% + 0
else if (value == "null")
value := ""
else
; we can do more here to pinpoint the actual culprit
; but that's just too much extra work.
this.ParseError(next, text, pos, i)
pos += i-1
}
next := holder==root ? "" : is_array ? ",]" : ",}"
} ; If InStr("{[", ch) { ... } else
is_array? key := ObjPush(holder, value) : holder[key] := value
if (this.keys && this.keys.HasKey(holder))
this.keys[holder].Push(key)
}
} ; while ( ... )
return this.rev ? this.Walk(root, "") : root[""]
}
ParseError(expect, ByRef text, pos, len:=1) {
static quot := Chr(34), qurly := quot . "}"
line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
, (expect == "") ? "Extra data"
: (expect == "'") ? "Unterminated string starting at"
: (expect == "\") ? "Invalid \escape"
: (expect == ":") ? "Expecting ':' delimiter"
: (expect == quot) ? "Expecting object key enclosed in double quotes"
: (expect == qurly) ? "Expecting object key enclosed in double quotes or object closing '}'"
: (expect == ",}") ? "Expecting ',' delimiter or object closing '}'"
: (expect == ",]") ? "Expecting ',' delimiter or array closing ']'"
: InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
: "Expecting JSON value (string, number, true, false, null, object or array)"
, line, col, pos)
static offset := A_AhkVersion < "2" ? -3 : -4
throw Exception(msg, offset, SubStr(text, pos, len))
}
Walk(holder, key) {
value := holder[key]
if IsObject(value) {
for i, k in this.keys[value] {
; check if ObjHasKey(value, k) ??
v := this.Walk(value, k)
if (v != JSON.Undefined)
value[k] := v
else
ObjDelete(value, k)
}
}
return this.rev.Call(holder, key, value)
}
}
class Dump extends JSON.Functor {
Call(self, value, replacer := "", space := "") {
this.rep := IsObject(replacer) ? replacer : ""
this.gap := ""
if (space) {
static integer := "integer"
if space is %integer%
Loop, % ((n := Abs(space))>10 ? 10 : n)
this.gap .= " "
else
this.gap := SubStr(space, 1, 10)
this.indent := "`n"
}
return this.Str({"": value}, "")
}
Str(holder, key) {
value := holder[key]
if (this.rep)
value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)
if IsObject(value) {
; Check object type, skip serialization for other object types such as
; ComObject, Func, BoundFunc, FileObject, RegExMatchObject, Property, etc.
static type := A_AhkVersion < "2" ? "" : Func("Type")
if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
if (this.gap) {
stepback := this.indent
this.indent .= this.gap
}
is_array := value.IsArray
; Array() is not overridden, rollback to old method of
; identifying array-like objects. Due to the use of a for-loop
; sparse arrays such as '[1,,3]' are detected as objects({}).
if (!is_array) {
for i in value
is_array := i == A_Index
until !is_array
}
str := ""
if (is_array) {
Loop, % value.Length() {
if (this.gap)
str .= this.indent
v := this.Str(value, A_Index)
str .= (v != "") ? v . "," : "null,"
}
} else {
colon := this.gap ? ": " : ":"
for k in value {
v := this.Str(value, k)
if (v != "") {
if (this.gap)
str .= this.indent
str .= this.Quote(k) . colon . v . ","
}
}
}
if (str != "") {
str := RTrim(str, ",")
if (this.gap)
str .= stepback
}
if (this.gap)
this.indent := stepback
return is_array ? "[" . str . "]" : "{" . str . "}"
}
} else ; is_number ? value : "value"
return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
}
Quote(string) {
static quot := Chr(34), bashq := "\" . quot
if (string != "") {
string := StrReplace(string, "\", "\\")
, string := StrReplace(string, "/", "\/") ; optional in ECMAScript
, string := StrReplace(string, quot, bashq)
, string := StrReplace(string, "`b", "\b")
, string := StrReplace(string, "`f", "\f")
, string := StrReplace(string, "`n", "\n")
, string := StrReplace(string, "`r", "\r")
, string := StrReplace(string, "`t", "\t")
static rx_escapable := A_AhkVersion < "2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
while RegExMatch(string, rx_escapable, m)
string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
}
return quot . string . quot
}
}
Undefined[] {
get {
static empty := {}, vt_empty := ComObject(0, &empty, 1)
return vt_empty
}
}
class Functor {
__Call(method, ByRef arg, args*) {
if IsObject(method)
return (new this).Call(method, arg, args*)
else if (method == "")
return (new this).Call(arg, args*)
}
}
}
- [AHK].......: 1.1.33.02 Unicode 64-bit
- [OS].........: Windows 10.0.19041
- [GITHUB]...: github.com/DeltaPyth
- [PAYPAL]....: paypal.me/DelPyth
- [DISCORD]..: Tophat Cat // Delta#8888
Remember to use [code]CODE[/code] for your multi-line scripts.
Stay safe, stay inside, and remember to wash your hands for 20 seconds!
Re: Youtube to MP3
Delta Pythagorean - I copied that code into the script, it doesn't say what the hotkey is, and I can't figure it out (very new to coding). Thanks in advance
Re: Youtube to MP3
edit: thanks to burque505 i just realized how much of a douche i sounded like. please forgives me delta. just didnt want to take away from HIACs hard work. 

Last edited by Wickster on 16 Nov 2017, 15:32, edited 2 times in total.
Re: Youtube to MP3
HIAC and Delta Pythagorean, thanks to both of you.
DP, that's a nice GUI. Took a second to realize the button was to paste the clipboard
Nice of you to not only give credit to HIAC in the GUI (not just the code!) but to also link HIAC's OP. Don't see that very often.
Regards,
burque505
p.s. DP, just tried to download an MP4, but only the MP3 downloaded. I'm sure the reason is that I first downloaded the MP3, then chose the same URL and tried to download the MP4 with the same name. It worked fine when I changed the name to something different than what I'd used for the MP3.
DP, that's a nice GUI. Took a second to realize the button was to paste the clipboard

Nice of you to not only give credit to HIAC in the GUI (not just the code!) but to also link HIAC's OP. Don't see that very often.
Regards,
burque505
p.s. DP, just tried to download an MP4, but only the MP3 downloaded. I'm sure the reason is that I first downloaded the MP3, then chose the same URL and tried to download the MP4 with the same name. It worked fine when I changed the name to something different than what I'd used for the MP3.
Return to “Scripts and Functions”
Jump to
- AutoHotkey Foundation
- About This Community
- Forum Issues
- AutoHotkey
- Ask For Help
- Gaming
- AutoHotkey v2 Help
- Scripts and Functions
- Gaming
- AutoHotkey v2 Scripts and Functions
- Tutorials
- Tips and Tricks
- Wish List
- Suggestions on documentation improvements
- Bug Reports
- AutoHotkey v2 Development
- AutoHotkey_H
- Ask For Help
- Development
- Announcements
- Editors
- AHK Studio
- Pulovers Macro Creator
- SciTE4AutoHotkey
- AutoGUI
- General Discussion
- General
- Other Utilities & Resources
- Other Programming Languages
- C/C++
- ASM
- C#
- Offtopic
- RPA
- Other languages
- Deutsch (German)
- Ich brauche Hilfe
- Spiele
- Skripte und Funktionen
- Tutorials
- Tooltime
- Allgemeines
- 中文 (Chinese)
- 请求帮助
- 脚本函数
- 教程资料
- 相关工具
- 其他
- Español (Spanish)
- Pedir Ayuda
- Automatización de Juegos
- Scripts y Funciones
- Tutoriales
- Otras Utilidades y Recursos
- General
- Русский (Russian)
- Помощь
- Скрипты для Игр
- Скрипты и библиотеки
- Статьи и руководства
- Прочие ресурсы и ПО.
- Свободное общение
- Français (French)
- J'ai besoin d'aide
- Scripts et Fonctions
- Tutoriels
- Autres Utilitaires et Ressources
- Hors Sujet
- Português (Portuguese)
- Ajuda e Suporte Geral
- Scripts e Funções
- Tutoriais
- Outras Ferramentas e Recursos
- Outros Assuntos
- 한국어 (Korean)