Is there any way to invoke chromedriver's Page.printToPDF() method from python + selenium?
PhantomJS has a similar render() method that can save straight to pdf, which is only available from the privileged client-side REPL of phantomjs. This SO answer shows how to patch a running selenium driver to invoke it, using a custom phantomjs webdriver command (/session/$sessionId/phantom/execute
) to call this.render()
.
Is there something similar that can be done for chromedriver? Either something like phantomjs's execute
command that allows calling into the devtools methods; or a way to invoke printToPDF
directly via a custom driver command?
(Note: I'm trying to render html that's the result of a POST, so alternate solutions like wkhtmltopdf won't work. I can fall back to using selenium's screenshot -> png, but that's burdensome for storage purposes).
It's possible by calling Page.printToPDF
from the DevTool API. However this command is experimental and not implemented on all the platforms:
from selenium import webdriver
import json, base64
def send_devtools(driver, cmd, params={}):
resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
url = driver.command_executor._url + resource
body = json.dumps({'cmd': cmd, 'params': params})
response = driver.command_executor._request('POST', url, body)
if response['status']:
raise Exception(response.get('value'))
return response.get('value')
def save_as_pdf(driver, path, options={}):
# https://timvdlippe.github.io/devtools-protocol/tot/Page#method-printToPDF
result = send_devtools(driver, "Page.printToPDF", options)
with open(path, 'wb') as file:
file.write(base64.b64decode(result['data']))
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.google.co.uk/")
save_as_pdf(driver, r'page.pdf', { 'landscape': False })
OK, only for reference, this is how I made it work on 2019 without generating an exception:
def send_devtools(driver, cmd, params={}):
resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
url = driver.command_executor._url + resource
body = json.dumps({'cmd': cmd, 'params': params})
response = driver.command_executor._request('POST', url, body)
#print (response)
if (response.get('value') is not None):
return response.get('value')
else:
return None
def save_as_pdf(driver, path, options={}):
# https://timvdlippe.github.io/devtools-protocol/tot/Page#method-printToPDF
result = send_devtools(driver, "Page.printToPDF", options)
if (result is not None):
with open(path, 'wb') as file:
file.write(base64.b64decode(result['data']))
return True
else:
return False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With