Page 7 of 7

Re: Get the URL of the current (active) browser tab

Posted: 05 Aug 2018, 16:14
by JnLlnd
AHKStudent wrote:in chrome 67 and 68 if you have a new tab window as the main window this wont work

to test click to get a new tab in chrome and then run to get list of windows, u will get blank even if you have 5 other regular websites opne
@AHKStudent: If we are talking of the same function GetActiveBrowserURL(), this function retrieves the active tab's URL. What you describe is not an error since there is no URL to retrieve in a blank tab.

@atnbueno: I hope you or another wizard here will be able to look into the Firefox issue...

Re: Get the URL of the current (active) browser tab

Posted: 09 Aug 2018, 02:35
by Johnny R
No atnbueno, no solution. Where is atnbueno?

Re: Get the URL of the current (active) browser tab

Posted: 18 Aug 2018, 08:09
by Johnny R
I've reinstalled the newest version of the script and the problem was solved. The script works fine with Firefox v61.0.2. Thank You all!

Re: Get the URL of the current (active) browser tab

Posted: 19 Aug 2018, 13:22
by JnLlnd
I confirm. This works with Firefox v61.0.2: ... 81#p182981

Re: Get the URL of the current (active) browser tab

Posted: 22 Oct 2018, 08:20
by hotkeyguy
I'm using JnLlnds code. With Firefox 62.0.3, I get sometimes two error messages
1. An error occurred in the secure channel support
followed by
2. The data necessary to complete this operation is not yet available.

The affected lines are objWebRequest.Send() ; and return (objWebRequest.StatusText() = "OK" ? objWebRequest.ResponseText() : "") in function Url2Var(strUrl):

Code: Select all

	objWebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	if (A_LastError)
		; an error occurred during ComObjCreate (A_LastError probably is E_UNEXPECTED = -2147418113 #0x8000FFFFL)
		BUT DO NOT ABORT because the following commands will be executed even if an error occurred in ComObjCreate (!)
	objWebRequest.Open("GET", strUrl)
	objWebRequest.Send() ; <== ERROR 1

	return (objWebRequest.StatusText() = "OK" ? objWebRequest.ResponseText() : "") ; <== ERROR 2
That happens e. g. with GitHub pages, like GitHub - nshalabi/SysmonTools: Utilities for Sysmon.
I assume that's an certificate validation issue? I tried Sleep instructions without success.

Many thanks for all your efforts and any hints

Re: Get the URL of the current (active) browser tab

Posted: 22 Oct 2018, 08:41
by JnLlnd

> I'm using JnLlnds code. With Firefox 62.0.3, I get sometimes two error messages

I tried only a few times but it worked with the same Firefox version.

BTW, I worked on in but I'm not the one who wrote the "core" of the code. It is from atnbueno.


Re: Get the URL of the current (active) browser tab

Posted: 21 Feb 2019, 09:43
by freespacing
Spanish version just because…
¡Hola atnbueno!
Gracias por el post con todo lujo de detalles.
Por casualidad ¿tendrías alguna sugerencia para Pale Moon?
De costumbre lo hago con JS dentro de Dorando o GreaseMonkey, pero me resultaría sumamente útil hacerlo en ahk.
Gracias y hasta pronto.

English because that's this board's language
Hello atnbueno!
Thanks for the post full of details.
Do you by any chance have any suggestions for Pale Moon?
I usually do it with JS inside Dorando or GreaseMonkey, but it would be extremely useful to do it in ahk.

Re: Get the URL of the current (active) browser tab

Posted: 02 Jul 2019, 08:36
by Dest938572
atnbueno wrote:
08 Jun 2014, 13:19

Short version: The code below finds out the URL of the current (active) browser tab for most of the modern browsers.
Awesome script, thank you Antonio.
It works perfect more than 5 years.

Re: Get the URL of the current (active) browser tab

Posted: 18 Nov 2019, 04:00
by tdalon
Hi Antonio
I have noticed an issue (Win10) with Internet Explorer.
If I have multiple windows opened, it returns the url of the first opened window and not the one where I have the focus on.

Re: Get the URL of the current (active) browser tab

Posted: 13 Feb 2020, 09:51
by tdalon
Would be great if it could support Vivaldi.
My workaround is to have:

Code: Select all

If WinActive("ahk_exe vivaldi.exe") {
		Send ^l
		sURL := GetSelection()
		return sURL
		Send {Esc}
I forgot to post:

Code: Select all

; Syntax:
; 	sSelection:=GetSelection()

OldClipboard:= ClipboardAll                         ;Save existing clipboard.

Send,^c                                          ;Copy selected text to clipboard
  sSelection := clipboard

; Restore Clipboard
Clipboard:= OldClipboard 
return sSelection

Re: Get the URL of the current (active) browser tab

Posted: 14 Feb 2020, 10:39
by rommmcek
Recently is saw this beautiful way, I use often too.
If you still have problems just repost!

Re: Get the URL of the current (active) browser tab

Posted: 14 Feb 2020, 15:54
by garry
rommmcek, thank you , and I used ctr+l for firefox and chrome ( maybe also for other browsers ( ? ) )

Re: Get the URL of the current (active) browser tab

Posted: 14 Feb 2020, 17:45
by rommmcek
@garry: AFAIK we have already history... For FF works ^l as well as !d. For most browsers does, although the first one seems to be more universal.

Re: Get the URL of the current (active) browser tab

Posted: 15 Feb 2020, 10:14
by garry
for firefox also alt+s

Re: Get the URL of the current (active) browser tab

Posted: 04 Apr 2020, 12:57
by tdalon
The workaround to focus / select the omnibox/ adress bar is a poor workaround: I don't want to move my cursor/position of my mouse when calling the function.

Re: Get the URL of the current (active) browser tab

Posted: 07 Apr 2020, 08:27
by rommmcek
Did you try to run Vivaldi with --force-renderer-accessibility switch?

Re: Get the URL of the current (active) browser tab

Posted: 01 May 2020, 02:52
Would someone mind to PayPal Antonio AKA @atnbueno a beer (or two! :shh:) to do an annual check on all of these different browsers?
And thx 4 sharing this marvelous piece of code :thumbup:

Re: Get the URL of the current (active) browser tab

Posted: 14 May 2020, 18:20
by thomastthai
Thank you @atnbueno for this excellent function. On a Windows 10 64-bit system (with latest updates as of 2020-05-14) running both Chrome (Version 81.0.4044.138) and Internet Explorer 11, AHK Version With both Chrome and IE running, even if I click on IE last to make it active, or with all instances of Chrome gone, the script defaults to checking Chrome when running from Visual Studio Code.

Window Spy reports VS Code as having Chrome_WidgetWin_1 as ahk_class. I'm unsure if that caused issues, but that was the class the script kept getting. [UPDATE: I found out VS Code uses Electron which is based on Chromium.] I needed it to get the ahk_class IEFrame. I don't fully understand all the code, but I'm unsure if it checks against ahk_exe and combines with ahk_class.

I am curious why the variables LegacyBrowsers and ModernBrowsers sit outside the function instead of inside?

I added a parameter and supporting code to "force" it to check the legacy browser first. Comments and notes are included in the code.

Code: Select all

; AutoHotkey Version:	AutoHotkey 1.1
; Language:				English
; Platform:				Win7 SP1 / Win8.1 / Win10
; Author:				Antonio Bueno <user atnbueno of Google's popular e-mail service>
; Short description:	Gets the URL of the current (active) browser tab for most modern browsers
; Change log:			
; 		2020-05-13		1) Added legacy parameter and code to "force" checking legacy 
;						browser first. 2) Replaced "Last mod:" field in the description
;						with "Change log:" to track changes. 3) Commented out and added instruction
;						in the demo section so current users can do an in-place update to their lib.
;						Thomas T. Thai <[email protected]>
;		2016-05-19		Last update by Antonio Bueno <[email protected]>

; Move these to variables to the top so they are automatically defined when this
; file is included and the demo is commented out. @thomastthai
ModernBrowsers := "ApplicationFrameWindow,Chrome_WidgetWin_0,Chrome_WidgetWin_1,Maxthon3Cls_MainFrm,MozillaWindowClass,Slimjet_WidgetWin_1"
LegacyBrowsers := "IEFrame,OperaWindowClass"

; --- <Demo> -------------------------------------------------------------------
; Instructions
; ------------
; To run the demo, uncomment the two lines indicated by the <--- arrows below.
/* ; <--- remove the */ to uncomment to run the demo
Menu, Tray, Icon, % A_WinDir "\system32\netshell.dll", 86 ; Shows a world icon in the system tray

^+!u:: ; Ctrl-Alt-Shift u
	nTime := A_TickCount
	sURL := GetActiveBrowserURL(True)
	WinGetClass, sClass, A
	If (sURL != "")
		MsgBox, % "The URL is """ sURL """`nEllapsed time: " (A_TickCount - nTime) " ms (" sClass ")"
	Else If sClass In % ModernBrowsers "," LegacyBrowsers
		MsgBox, % "The URL couldn't be determined (" sClass ")"
		MsgBox, % "Not a browser or browser not supported (" sClass ")"
*/ ; <--- remove the */ to uncomment to run the demo
; --- </Demo> ------------------------------------------------------------------

GetActiveBrowserURL(legacy = False) {
	global ModernBrowsers, LegacyBrowsers

	; @thomastthai - added parameter legacy and added the code below to handle 
	; systems where modern browser and legacy browsers are both running. 
	; My Windows 10 Pro system defaults to checking Chrome instead of 
	; Internet Explorer 11. and we want to check on the legacy active window.
	if legacy {
		WinGetClass, sClass, ahk_class IEFrame
		If (sClass = "")
			WinGetClass, sClass, ahk_class OperaWindowClass
		WinGetClass, sClass, A

	If sClass In % ModernBrowsers
		Return GetBrowserURL_ACC(sClass)
	Else If sClass In % LegacyBrowsers
		Return GetBrowserURL_DDE(sClass) ; empty string if DDE not supported (or not a browser)
		Return ""

; "GetBrowserURL_DDE" adapted from DDE code by Sean, (AHK_L version by maraskan_user)
; Found at

GetBrowserURL_DDE(sClass) {
	WinGet, sServer, ProcessName, % "ahk_class " sClass
	StringTrimRight, sServer, sServer, 4
	iCodePage := A_IsUnicode ? 0x04B0 : 0x03EC ; 0x04B0 = CP_WINUNICODE, 0x03EC = CP_WINANSI
	DllCall("DdeInitialize", "UPtrP", idInst, "Uint", 0, "Uint", 0, "Uint", 0)
	hServer := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", sServer, "int", iCodePage)
	hTopic := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "WWW_GetWindowInfo", "int", iCodePage)
	hItem := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "0xFFFFFFFF", "int", iCodePage)
	hConv := DllCall("DdeConnect", "UPtr", idInst, "UPtr", hServer, "UPtr", hTopic, "Uint", 0)
	hData := DllCall("DdeClientTransaction", "Uint", 0, "Uint", 0, "UPtr", hConv, "UPtr", hItem, "UInt", 1, "Uint", 0x20B0, "Uint", 10000, "UPtrP", nResult) ; 0x20B0 = XTYP_REQUEST, 10000 = 10s timeout
	sData := DllCall("DdeAccessData", "Uint", hData, "Uint", 0, "Str")
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hServer)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hTopic)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hItem)
	DllCall("DdeUnaccessData", "UPtr", hData)
	DllCall("DdeFreeDataHandle", "UPtr", hData)
	DllCall("DdeDisconnect", "UPtr", hConv)
	DllCall("DdeUninitialize", "UPtr", idInst)
	csvWindowInfo := StrGet(&sData, "CP0")
	StringSplit, sWindowInfo, csvWindowInfo, `" ;"; comment to avoid a syntax highlighting issue in
	Return sWindowInfo2

GetBrowserURL_ACC(sClass) {
	global nWindow, accAddressBar
	If (nWindow != WinExist("ahk_class " sClass)) ; reuses accAddressBar if it's the same window
		nWindow := WinExist("ahk_class " sClass)
		accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindow))
	Try sURL := accAddressBar.accValue(0)
	If (sURL == "") {
		WinGet, nWindows, List, % "ahk_class " sClass ; In case of a nested browser window as in the old CoolNovo (TO DO: check if still needed)
		If (nWindows > 1) {
			accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindows2))
			Try sURL := accAddressBar.accValue(0)
	If ((sURL != "") and (SubStr(sURL, 1, 4) != "http")) ; Modern browsers omit "http://"
		sURL := "http://" sURL
	If (sURL == "")
		nWindow := -1 ; Don't remember the window if there is no URL
	Return sURL

; "GetAddressBar" based in code by uname
; Found at

GetAddressBar(accObj) {
	Try If ((accObj.accRole(0) == 42) and IsURL(accObj.accValue(0)))
		Return accObj
	Try If ((accObj.accRole(0) == 42) and IsURL("http://" accObj.accValue(0))) ; Modern browsers omit "http://"
		Return accObj
	For nChild, accChild in Acc_Children(accObj)
		If IsObject(accAddressBar := GetAddressBar(accChild))
			Return accAddressBar

	Return RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^:/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")

; The code below is part of the Acc.ahk Standard Library by Sean (updated by jethrow)
; Found at

	static h
	If Not h
Acc_ObjectFromWindow(hWnd, idObject = 0)
	If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return ComObjEnwrap(9,pacc,1)
Acc_Query(Acc) {
	Try Return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
Acc_Children(Acc) {
	If ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	Else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		If DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			Return Children.MaxIndex()?Children:
		} Else
			ErrorLevel := "AccessibleChildren DllCall Failed"

Re: Get the URL of the current (active) browser tab

Posted: 17 Aug 2020, 18:37
by conracer
I have read all the code in this thread and here is my solution (caution - thank you tdalon: from system to system the Acc-path can vary!):

Code: Select all

#Include AccV2.ahk ;

F7::MsgBox % GetURL()

GetUwpAppName() {
    WinGet name,ProcessName,A
    if(name="ApplicationFrameHost.exe") {
        ControlGet hWnd,Hwnd,,Windows.UI.Core.CoreWindow1,A
            WinGet name,ProcessName,ahk_id %hWnd%
    return name

GetURL() {
	if(WinActive("ahk_exe chrome.exe"))
		return Acc_Get("Object","",0,"A").accValue(0)
	if(WinActive("ahk_exe firefox.exe"))
		return Acc_Get("Object","",0,"A").accValue(0)
	if(WinActive("ahk_class IEFrame"))
		return Acc_Get("Object","",0,"A").accValue(0)
	if(GetUwpAppName()="MicrosoftEdge.exe") {
		Loop % items.length()
				return items[A_Index].accValue(0)
	Sleep 100
	Send ^l^c ; Ctrl+l would also work in ALL four browsers from above. But nevertheless: this line is untested!
	ClipWait 0.1
	return url
BTW: It is not that much work to go through the AccViewer.ahk-tree to find what you want