title: Python Selenium take screenshots and Save as PDF for windows opened with document.write()
body: <p>I'm using Selenium with Python (in Jupyter notebook). I have a number of tabs open, say 5 tabs (with all elements already finished loading) and I would like to cycle through them and do 2 things:</p>
  <ol>
  <li>Take a screenshot,</li>
  <li>(As a bonus) Print each to PDF using Chrome's built-in Save as PDF function using A4 landscape, normal scaling, and a specified default directory, with no user interaction required.</li>
  </ol>
  <p>(In the code below I focus on the screenshot requirement, but would also very much like to know how to Save it as a PDF)</p>
  <p>This code enables looping through the tabs:</p>
  <pre><code>numTabs = len(driver.window_handles)
  for x in range(numTabs):
      driver.switch_to.window(driver.window_handles[x])    
      time.sleep(0.5)     
  </code></pre>
  <p>However, if I try to add a <code>driver.save_screenshot()</code> call as shown below, the code seems to halt after taking the first screenshot. Specifically, '0.png' is created for the first tab (with index 0) and it switches to the next tab (with index 1) but stops processing further. It doesn't even cycle to the next tab.</p>
  <pre><code>numTabs = len(driver.window_handles)
  for x in range(numTabs):
      driver.switch_to.window(driver.window_handles[x])    
      driver.save_screenshot(str(x) + '.png') #screenshot call
      time.sleep(0.5)    
  </code></pre>
  <p><strong>Edit1:</strong>
  I modified the code as shown below to start taking the screenshots from <code>window_handles[1]</code> instead of <code>[0]</code> as I don't really need the screenshot from <code>[0]</code>, but now not even a single screenshot is generated. So it seems that the <code>save_screenshot()</code> call doesn't work after even the initial <code>switch_to.window()</code> call.</p>
  <pre><code>tabs = driver.window_handles
  for t in range(1, len(tabs)):
      print(&quot;Processing tab &quot; + tabs[t]) 
      driver.switch_to.window(tabs[t])  
      driver.save_screenshot(str(t) + '.png') #screenshot call, but the code hangs. No screenshot taking, no further cycling through tabs.
  </code></pre>
  <p><strong>Edit2:</strong>
  I've found out why my code is &quot;hanging&quot;, no matter which method of printing to PDF or taking screenshots I'm using. I mentioned earlier that the new tabs were opened via clicking on buttons from the main page, but upon closer inspection, I see now that the content of the new tabs is generated using <code>document. write()</code>. There's some ajax code that retrieves <em>waybillHTML</em> content that is then written into a new window using <code>document.write(waybillHTML)</code></p>
  <p>For more context, this is an orders system, with the main page with a listing of orders, and a button next to each order that opens up a new tab with a waybill. And the important part is that the waybills are actually generated using <code>document. write()</code> triggered by the button clicks. I notice that the &quot;View page source&quot; option is greyed out when right-clicking in the new tabs. When I  use <code>switch_to.window()</code> to switch to one of these tabs, the <code>Page.printToPDF</code> <strong>times out</strong> after 300 (seconds I suppose).</p>
  <pre><code>---------------------------------------------------------------------------
  TimeoutException                          Traceback (most recent call last)
  &lt;ipython-input-5-d2f601d387b4&gt; in &lt;module&gt;
       14     driver.switch_to.window(handles[x])
       15     time.sleep(2)
  ---&gt; 16     data = driver.execute_cdp_cmd(&quot;Page.printToPDF&quot;, printParams)
       17     with open(str(x) + '.pdf', 'wb') as file:
       18         file.write(base64.b64decode(data['data']))
  
  ...
  
  TimeoutException: Message: timeout: Timed out receiving a message from renderer: 300.000
    (Session info: headless chrome=96.0.4664.110)
  </code></pre>
  <p>So my refined question should be how to use <code>Page.printToPDF</code> to print a page in a new window (that is generated dynamically with <code>document. write()</code>) without <strong>timing out</strong>?</p>
  <p>One approach I tried was to do this:</p>
  <pre><code>from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
  caps = DesiredCapabilities().CHROME
  caps[&quot;pageLoadStrategy&quot;] = &quot;none&quot;
  driver = webdriver.Chrome(options=chrome_options, desired_capabilities=caps)
  </code></pre>
  <p>referring to: <a href="https://stackoverflow.com/questions/48450594/selenium-timed-out-receiving-message-from-renderer">this question</a></p>
  <p>but the problem is this is too 'aggressive' and prevents the code from logging into the ordering system and doing the navigating &amp; filtering necessary to get the browser to the point where I get the orders listing page with the waybill generating buttons (i.e. the original setup in this question).</p>
  <p><strong>Edit3:</strong>
  At this point, I've tried something as simple as just getting the page source</p>
  <pre><code>try:
      pageSrc = driver.find_element(By.XPATH, &quot;//*&quot;).get_attribute(&quot;outerHTML&quot;)
      print(pageSrc)
  </code></pre>
  <p>of the dynamically generated tabs (long after they had completed rendering and I can see the content on the screen (not using headless for this stage of the debugging)) and even this itself is throwing a TimeoutException, so I don't think it's an issue with waiting for content to load. Somehow the driver is unable to see the content. It might be something peculiar with how these pages are generated - I don't know. All the methods suggested in the answers for taking screenshots and saving PDFs are good I'm sure for otherwise normal windows. With Chrome the <code>View page source</code> remains greyed out, but I can see regular HTML content using <code>Inspect</code>.</p>
  <p><strong>Edit4:</strong>
  Using Chrome's Inspection function, the page source of the dynamically generated page has this HTML structure:</p>
  <p><a href="https://i.stack.imgur.com/W39Ty.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/W39Ty.png" alt="HTML structure of dynamically generated page" /></a></p>
  <p>Curiously, &quot;View page source&quot; remains greyed out even after I'm able to Inspect the contents:
  <a href="https://i.stack.imgur.com/UvMhd.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UvMhd.png" alt="enter image description here" /></a></p>
  <p><strong>Edit5:</strong>
  Finally figured it out. When I clicked on the button for generating the new tab, the site would make an ajax call to fetch the HTML content of the new page, and <code>document.write</code> it to a new tab. I suppose this is outside the scope of selenium to handle. Instead, I imported <a href="https://pypi.org/project/selenium-wire/1.0.3/" rel="nofollow noreferrer">selenium-wire</a>, used <code>driver.wait_for_request</code> to intercept the ajax call, parsed the response containing the HTML code of the new tab, and dumped the cleaned HTML into a new file. From then on generating the PDF can be easily handled using a number of ways as others have already suggested.</p>