19

I am trying to ZOOM IN and ZOOM OUT the Chrome( selenium webdriver) only using keyboard. I have tried --

from selenium.webdriver.common.keys import Keys
driver.find_element_by_tag_name("body").send_keys(Keys.CONTROL,Keys.SUBTRACT). 

but it is not working. Need answer in python.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Dayananda
  • 305
  • 1
  • 2
  • 11

6 Answers6

18

I was just struggling with this. I managed to find something that works for me, hopefully it works for you:

driver.execute_script("document.body.style.zoom='zoom %'")

Have 'zoom%' = whatever zoom level you want. (e.g. '67%')

Ben
  • 2,308
  • 2
  • 18
  • 25
  • 15
    For me it's not working with Selenium 2.53 and Firefox – oxidworks Aug 31 '16 at 11:05
  • @oxidworks did you try OP's syntax (which comes from [ActionChains](http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains))? That seems to work for webdrivers besides Chrome. – Ben Apr 03 '17 at 19:56
  • If your browser is already zoomed, the current zoom is threated as 100%. This doesn't equal to send CONTROL + 0 to the browser to reset zoom. – m3nda Sep 11 '20 at 14:19
18

Environment:

  • Selenium 3.6.0
  • chromedriver 2.33
  • Chrome version 62.0.3202.75 (Official Build) (64-bit)
  • macOS Sierra 10.12.6

I tried the ways (without use the CSS) that people suggested in other questions in the past. For example, the answers in this question: Selenium webdriver zoom in/out page content.

Or this: Test zoom levels of page on browsers

without success.

So, I thought: if not with the shortcuts, what could be a different way to do that?

The idea is to use the "chrome://settings/" page in order to change the zoom:

enter image description here

Ok I know, for example from Going through Chrome://settings by Selenium, that every settings should be set in the ChromeOptions.

From this question I noticed that in the list of preferences the only paramater (I think) could be:

// Double that indicates the default zoom level.
const char kPartitionDefaultZoomLevel[] = "partition.default_zoom_level";

I tried, without success.

I want to repeat that I know it isn't the correct approach (and that will be different with different browser versions), but it works and, at least, was useful for me to understand how to go inside a shadow root element with selenium.

The following method return the elements inside a shadow root:

def expand_shadow_element(element):
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
    return shadow_root

It is useful because in the chrome://settings/ page there are shadow root elements.

In order to do that in my browser, this is the path:

root1=driver.find_element_by_xpath("*//settings-ui")
shadow_root1 = expand_shadow_element(root1)
container= shadow_root1.find_element_by_id("container")

root2= container.find_element_by_css_selector("settings-main")
shadow_root2 = expand_shadow_element(root2)

root3=shadow_root2.find_element_by_css_selector("settings-basic-page")

shadow_root3 = expand_shadow_element(root3)
basic_page = shadow_root3.find_element_by_id("basicPage")

enter image description here

settings_section= basic_page.find_element_by_xpath(".//settings-section[@section='appearance']")

root4= settings_section.find_element_by_css_selector("settings-appearance-page")
shadow_root4=expand_shadow_element(root4)

enter image description here

and finally:

settings_animated_pages= shadow_root4.find_element_by_id("pages")
neon_animatable=settings_animated_pages.find_element_by_css_selector("neon-animatable")

zoomLevel= neon_animatable.find_element_by_xpath(".//select[@id='zoomLevel']/option[@value='0.5']")
zoomLevel.click()

enter image description here

The entire code:

driver = webdriver.Chrome(executable_path=r'/pathTo/chromedriver')

def expand_shadow_element(element):
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
    return shadow_root


driver.get('chrome://settings/')

root1=driver.find_element_by_xpath("*//settings-ui")
shadow_root1 = expand_shadow_element(root1)
container= shadow_root1.find_element_by_id("container")

root2= container.find_element_by_css_selector("settings-main")
shadow_root2 = expand_shadow_element(root2)

root3=shadow_root2.find_element_by_css_selector("settings-basic-page")

shadow_root3 = expand_shadow_element(root3)
basic_page = shadow_root3.find_element_by_id("basicPage")

settings_section= basic_page.find_element_by_xpath(".//settings-section[@section='appearance']")

root4= settings_section.find_element_by_css_selector("settings-appearance-page")
shadow_root4=expand_shadow_element(root4)

settings_animated_pages= shadow_root4.find_element_by_id("pages")
neon_animatable=settings_animated_pages.find_element_by_css_selector("neon-animatable")

zoomLevel= neon_animatable.find_element_by_xpath(".//select[@id='zoomLevel']/option[@value='0.5']")
zoomLevel.click()


driver.get("https://www.google.co.uk/")

EDIT

As suggested by @Florent B in the comments, we can obtain the same result simple with:

driver.get('chrome://settings/')
driver.execute_script('chrome.settingsPrivate.setDefaultZoom(1.5);')
driver.get("https://www.google.co.uk/")

enter image description here

Community
  • 1
  • 1
Davide Patti
  • 3,391
  • 2
  • 18
  • 20
  • Sorry but I got stuck at the beginning in `root1=driver.find_element_by_xpath("*//settings-ui")`. how did you define driver? I get a NoSuchElementException – splinter Nov 03 '17 at 15:37
  • @splinter what is the version of your chrome browser? as I said in the answer, I think depends on this. If you inspect the html in your "chrome://settings/", is the same of mine? Anyway, at the end of the answer there is the entire code. – Davide Patti Nov 03 '17 at 15:43
  • 4
    Instead of updating the DOM, you could simply call the API in the page: `driver.get("chrome://settings/")` then `driver.execute_script("chrome.settingsPrivate.setDefaultZoom(1.5);")`. – Florent B. Nov 03 '17 at 18:19
  • @FlorentB. Thanks, Is there a typing mistake in your call? because I obtain this exception: Runtime.evaluate threw exception: SyntaxError: Invalid or unexpected token – Davide Patti Nov 03 '17 at 18:35
  • @Davide Patti, it works just fine with my config (win10 chromium 62.0.3202.62). You can check the source [here](https://cs.chromium.org/search/?q=onZoomLevelChange_&type=cs). It could be a sync issue. Try with a timeout: `driver.execute_script("setTimeout(function(){chrome.settingsPrivate.setDefaultZoom‌​(1.5);}, 5);")` – Florent B. Nov 03 '17 at 18:58
  • 1
    @FlorentB. I got it the problem. If I copy and paste your example in the console of Chrome, I see 2 dots after "Zoom". Something like this: driver.execute_script("chrome.settingsPrivate.setDefaultZoom‌..​(1.5);"). In my ide (intelliJ) this dots weren't showed. That's why my error. If I remove this dots, works fine. Thanks. – Davide Patti Nov 08 '17 at 12:53
  • @FlorentB., you should post this as a solution rather than just in the comments. This is the only solution in which the zoom persists across page loads, and that's an incredibly useful behavior. – Tom Apr 12 '23 at 18:24
13

firefox solution for me,

Zoom body browser

zoom is a non-standard property, use transform instead (demo):

driver.execute_script("document.body.style.transform = 'scale(0.8)'")

https://github.com/SeleniumHQ/selenium/issues/4244

driver.execute_script('document.body.style.MozTransform = "scale(0.50)";')

driver.execute_script('document.body.style.MozTransformOrigin = "0 0";')

bluequijote
  • 131
  • 1
  • 2
  • The OP asked specifically about Chrome, not FireFox. Stack Overflow is a Q & A site, the answer box is only for complete answers to the question that was asked. You should put a bit more effort in. Test this solution in Chrome and indicate it works in the answer. Otherwise this should be made into a comment (which you will be able to do once you have earned enough reputation), as it is relevant but does not directly answer the question. – NightOwl888 Apr 09 '18 at 18:37
  • 2
    I found this solution useful and have not found a similar question asked for Firefox on SO, so happy this is here. – Ben Jan 04 '20 at 20:00
  • Same as the zoom property. If your browser is already zoomed, the current zoom is threated as 100%. This doesn't equal to send CONTROL + 0 to the browser to reset zoom. – m3nda Sep 11 '20 at 14:20
  • document.body.style.transform works on Chrome as well. – Tom Apr 12 '23 at 18:20
7

Yes, you can invoke the Chrome driver to zoom without having to use CSS. There are methods packaged into the Chrome DevTools Protocol Viewer, one being Input.synthesizePinchGesture aka zoom in/out.

For ease of use, with regards to the DevTools Protocol API, we will use a class called MyChromeDriver with webdriver.Chrome as a metaclass and a new method for sending these commands to Chrome:

# selenium
from selenium import webdriver
# json
import json

class MyChromeDriver(webdriver.Chrome):
    def send_cmd(self, cmd, params):
        resource = "/session/%s/chromium/send_command_and_get_result" % self.session_id
        url = self.command_executor._url + resource
        body = json.dumps({'cmd':cmd, 'params': params})
        response = self.command_executor._request('POST', url, body)
        return response.get('value')

1. Setup our webdriver and get some page:

webdriver = MyChromeDriver()
webdriver.get("https://google.com")

2. Send Chrome the Input.synthesizePinchGesture command along with its parameters via our new method send_cmd:

webdriver.send_cmd('Input.synthesizePinchGesture', {
                        'x': 0,
                        'y': 0,
                        'scaleFactor': 2,
                        'relativeSpeed': 800, # optional
                        'gestureSourceType': 'default' # optional
                    })

3. Walla! Chrome's zoom is invoked: enter image description here

As a side note, there are tons of other commands you could use with send_cmd. Find them here: https://chromedevtools.github.io/devtools-protocol/

Based off this answer: Take full page screen shot in Chrome with Selenium

Cole
  • 1,715
  • 13
  • 23
  • 1
    hi, Cole, i tried your code, it returns ```AttributeError: module 'selenium.webdriver' has no attribute 'send_cmd'```, do you have any idea on this issue? – Edison Toh Jun 13 '20 at 09:15
3

As you mentioned that Need it to work in Chrome. The current solutions are only for Firefox, here are a few updates and options :

  1. Zoom the CSS :

    driver.execute_script("document.body.style.zoom='150%'")
    

    This option did work for me. But it zooms the CSS, not the Chrome Browser. So probably you are not looking at that.

  2. Zoom In & Zoom Out the Chrome Browser :

After 4131, 4133 and 1621 the fullscreen() mode got supported to Zoom In through Selenium-Java Clients but it's not yet publicly released to PyPI.

I can see it's implemented but not pushed. Selenium 3.7 (Python) will be out soon. The push to sync version numbers will include that.

  1. Configure the webdriver to open the Browser :

If your requirement is to execute the Test Suite in Full Screen mode, you can always use the Options Class and configure the webdriver instance with --kiosk argument as follows:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--kiosk")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://www.google.co.in')
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
-1
# zoom in firefox browser
driver.get("about:preferences")
driver.execute_script("arguments[0].click();", driver.find_element(By.XPATH, "// [@id='defaultZoom']"))
ActionChains(driver).click(driver.find_element(By.XPATH, "//*[@value='50']")).perform()
The Thonnu
  • 3,578
  • 2
  • 8
  • 30
0gl04q
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 21 '22 at 14:21