-4

Out of the box, webdriver only takes a screenshot of the visible page area. Following on from this post, I would like to ask how to take a full page screenshot in Selenium using Java, when the page length is greater than the viewport?

The posts describing how to do this are either unanswered (such as this one) or point towards the AShot library (such as this one) which provides the functionality, but it has some issues which means I do not want to use it. Specifically, when using a remote driver on e.g. Browserstack, it only renders the left-hand half of the screenshot. In addition it is no longer maintained by the original author and so it seems more appropriate to write a new function for what is essentially a fairly simple problem.

Hester Lyons
  • 803
  • 11
  • 24

1 Answers1

2

Prerequisite: access to an instance of WebDriver. Mine is instantiated with the class the code lives in.

The main function that coordinates the size of the screenshot and the scrolling down the page is as follows. Note that the image format is to make it compatible with pdiff :

public void takeFullScreenshot(String outputFile) throws IOException {


        JavascriptExecutor js = ((JavascriptExecutor) webDriver);

        // Scroll right to the top
        js.executeScript("window.scrollTo(0,0)");

        // Get the height of the screen
        int windowHeight = ((Number) js.executeScript("return window.innerHeight")).intValue();

        // Get the total height of the page
        int pageHeight = ((Number) js.executeScript("return document.body.scrollHeight")).intValue();

        // Calculate the number of full screen shots
        double fullFraction = pageHeight / windowHeight;
        int fullShots = (int) fullFraction; // this simply removes the decimals

        // Initialise ouput image
        int imageWidth = webDriver.manage().window().getSize().width;
        BufferedImage fullScreenshot = new BufferedImage(imageWidth, pageHeight, BufferedImage.TYPE_4BYTE_ABGR);

        // Get the graphics
        Graphics2D fullGraphics = fullScreenshot.createGraphics();

        // Calculate our scroll script
        String script = "window.scrollBy(0," + String.valueOf(windowHeight) + ")";

        // Loop - for the required number of full screenshots
        for (int aShot = 0; aShot < fullShots; aShot ++) {

            // Sort out the screenshot and paste it in the correct place
            pasteScreenshot(fullGraphics, aShot * windowHeight);

            // scroll
            js.executeScript(script);
        }

        // Final phase - scroll to the bottom
        js.executeScript(script); // we know this goes too far down, but should be OK.

        // Take final screenshot and paste at the bottom
        pasteScreenshot(fullGraphics, pageHeight - windowHeight);

        // Save the whole thing to output file.
        ImageIO.write(fullScreenshot, "PNG", new File(outputFile));
    }

The little function that pastes the screenshot into the correct place in the output graphics is as follows:

private void pasteScreenshot (Graphics2D outputGraphics, int yCoordinate) throws IOException {
        // Take screenshot and hold it as an image
        File tmpFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
        BufferedImage tmpImage = ImageIO.read(tmpFile);

        // Draw it on the graphics of the final output image
        outputGraphics.drawImage(tmpImage, null, 0, yCoordinate);

    }

Hope this is useful.

Hester Lyons
  • 803
  • 11
  • 24