19

I am trying to save a canvas element as a png image. This is my code right now but, unfortunately, it does not work:

import time
from selenium import webdriver
# From PIL import Imag.


driver = webdriver.Firefox()
driver.get('http://www.agar.io')
driver.maximize_window()
driver.find_element_by_id('freeCoins').click()

time.sleep(2)

# The part below does not seem to work properly.

driver.execute_script('function download_image(){var canvas = document.getElementByTagName("canvas");canvas.toBlob(function(blob) {saveAs(blob, "../images/output.png");}, "image/png");};')

I would like to see the solution in Python. I would also like to see a solution that does not require cropping at the end of the screenshot.

Ratmir Asanov
  • 6,237
  • 5
  • 26
  • 40
Clone
  • 3,378
  • 11
  • 25
  • 41
  • Possible duplicate of [How to capture the screenshot of a specific element rather than entire page using Selenium Webdriver?](http://stackoverflow.com/questions/13832322/how-to-capture-the-screenshot-of-a-specific-element-rather-than-entire-page-usin) – JeffC Jul 11 '16 at 21:49
  • ...or better yet, http://stackoverflow.com/questions/15018372/how-to-take-partial-screenshot-with-selenium-webdriver-in-python – JeffC Jul 11 '16 at 21:50
  • I would like to see a solution other than having to crop the image. The first link you provide is Java. – Clone Jul 11 '16 at 22:31
  • There is no other way to take a picture of an element and not crop the screenshot. I looked and this is what I ended up using. Yep I linked it and then realized it was Java and you didn't ask for Java. Sorry about that but I couldn't edit it at that point so I posted one with the right language. – JeffC Jul 12 '16 at 03:29

1 Answers1

28

You could call HTMLCanvasElement.toDataURL() to get the canvas as PNG base64 string. Here is a working example:

import base64
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://curran.github.io/HTML5Examples/canvas/smileyFace.html")

canvas = driver.find_element_by_css_selector("#canvas")

# get the canvas as a PNG base64 string
canvas_base64 = driver.execute_script("return arguments[0].toDataURL('image/png').substring(21);", canvas)

# decode
canvas_png = base64.b64decode(canvas_base64)

# save to a file
with open(r"canvas.png", 'wb') as f:
    f.write(canvas_png)
Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • 1
    Why is the substring called with 21, it should be 22 to cut the comma, too. Has there changed something or is the decode ignoring the comma? By the way, which selenium version are you using where this is running. I get invalid base64 encoding, even if removing the comma. But in Chrome DevTools I can extract the correct base64 encoding this way. Looks like Selenium is doing it another way. – jan Jul 21 '22 at 09:56