4

Is it possible to set custom location coordinates with Chrome Headless? I can't find it in the Devtools protocol API. Is there a workaround available?

Matic Jurglič
  • 831
  • 9
  • 26

2 Answers2

4

I googled it and got many methods. I try one by one, almost all of them turn out outdated. Then I find out a solution, use chrome devtools protocol to achieve that.

The small example code below, that it uses the most common tool selenium to execute chrome devtools protocol command.

import time

from selenium.webdriver import Chrome, ChromeOptions

options = ChromeOptions()
options.add_argument("--headless")
driver = Chrome(options=options)
driver.execute_cdp_cmd(
    "Browser.grantPermissions",
    {
        "origin": "https://www.openstreetmap.org/",
        "permissions": ["geolocation"]
    },
)
driver.execute_cdp_cmd(
    "Emulation.setGeolocationOverride",
    {
        "latitude": 35.689487,
        "longitude": 139.691706,
        "accuracy": 100,
    },
)
driver.get("https://www.openstreetmap.org/")
driver.find_element_by_xpath("//span[@class='icon geolocate']").click()
time.sleep(3)  # wait for the page full loaded
driver.get_screenshot_as_file("screenshot.png")

screenshot.png

linw1995
  • 166
  • 1
  • 8
  • So many half-answers to this question on the web, but this answer actually works. Huge thank you. – rer Jun 04 '20 at 21:16
0

https://chromedevtools.github.io/devtools-protocol/tot/Emulation#method-setGeolocationOverride

and

https://chromedevtools.github.io/devtools-protocol/tot/Emulation#method-clearGeolocationOverride

... then you'll need to contend with ensuring that the correct location sharing setting is set within the user profile (chrome://settings/content/location - which is difficult to access due to being displayed via shadow dom, so using a preconfigured user profile will likely be easier --user-data-dir).

Edit to add: The above does not seem to be effective when using --headless. To resolve this I used https://chromedevtools.github.io/devtools-protocol/tot/Page#method-addScriptToEvaluateOnNewDocument with the following snippet:

navigator.geolocation.getCurrentPosition = function(success, failure) { 
    success({
        coords: {latitude: <your_lat_float>, longitude: <your_lng_float>}, 
        timestamp: Date.now(),
    }); 
}
Daved
  • 108
  • 2
  • 8