How to get screenshot of full webpage using Selenium and Java?
Asked Answered
N

13

27

How to take a screenshot of the entire web page (full-page screenshot), not only partial (top-to-bottom) using Selenium WebDriver?

My code: (Java bindings)

System.setProperty("webdriver.chrome.driver","/home/alex/Downloads/chromedriver_linux64/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("http://google.com");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(RESULT_FILENAME));

Any ideas on how to tackle this?

Noisome answered 20/5, 2017 at 12:12 Comment(1)
I have a Answer for you but I want to confirm if that works for you. So can you please consider detailing out what you mean by full entire web page, not only partial from the top using selenium ? ThanksCristie
E
25

LE: I see quite a lot of people are interested in the full-page screenshot, so I thought I might update the answer with some positives (silver bullets).

There are quite a handful of web testing frameworks that can (with minimal setup & effort) produce a full-page screenshot. I come from a NodeJS testing environment, so I can only vouch the following: WebdriverIO & Google's Puppeteer.

If anyone is interested in an easy way to do it with WebdriverIO, check this answer.


Short answer is NO, YOU CANNOT, if you're only using Selenium (detailed reason bellow). But, what you can do is make the most out of your device's(monitor) viewport.

So, start your browser instance (driver) using ChromeOptions(), which is the method for setting ChromeDriver-specific capabilities. We can do the following:

  • maximize the window (using the --start-maximized switch);
  • go full-screen (F11-key on Windows, Control+Cmd+F on Mac, using the --start-fullscreen switch).
  • Note: complete list of Chrome command-line-switches can be found here.

Your code should look like this:

// Setting your Chrome options (Desired capabilities)
ChromeOptions options = new ChromeOptions();
options.add_argument('--start-maximized');
options.add_argument('--start-fullscreen');

// Creating a driver instance with the previous capabilities
WebDriver driver = new ChromeDriver(options);

// Load page & take screenshot of full-screen page
driver.get("http://google.com");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

Now regarding the full page problem, all drivers (chromedriver, geckodriver, IEDriver, EdgeDriver, etc.) are implementing the WebDriver W3C standard. Thus, they are dependent on the way the WebDriver team wants to expose the functionality of different features, in our case, 'Take Screenshot'.

If you read the definition, it clearly states the following:

The Take Screenshot command takes a screenshot of the top-level browsing context’s VIEWPORT.

Legacy-wise, some drivers were able to produce a full-page screenshot (read more about it here), like the old FirefoxDriver, IEDriver, etc. That is no longer the case as they now all implement (to the letter) the WebDriver W3C standard.

Episode answered 20/5, 2017 at 12:58 Comment(0)
S
10

Now there's an easy way to do it with Selenium 4 and Firefox.

byte[] imageBytes = ((FirefoxDriver)driver).getFullPageScreenshotAs(OutputType.BYTES);
Files.write(Paths.get(RESULT_FILENAME), imageBytes);

Other browsers don't support getFullPageScreenshotAs() yet.

Splenetic answered 29/3, 2021 at 17:48 Comment(5)
Does this work for a full-page screenshot of "acrobat.adobe.com"? For me I only get a small viewport, not a full page.Decuple
Yes, a full-page screenshot of "acrobat.adobe.com" works fine for me with Selenium 4 beta 2.Splenetic
Ah, I had to use Thread.sleep(5000) for the page to load, and this is working now.Decuple
No amount of sleeping helps the page render correctly for me. Some elements appear strangely cut off.Germaun
don't sleep, instead: (new WebDriverWait(base.driver, Duration.ofSeconds(45))).until(ExpectedConditions.elementToBeClickable(By.xpath("//foo[bar]"))).click();Gaskell
T
7

Looks like this article suggesting AShot works for me. Also, I successfully embeded the full page screenshot into Cucumber report with following code

    scenario.embed(takeScreenShotAsByte(getWebDriver()), "image/png");

    private static byte[] takeScreenShotAsByte(WebDriver webDriver) throws IOException {
        return takeFullPageScreenShotAsByte(webDriver);
    }

    private static byte[] takeFullPageScreenShotAsByte(WebDriver webDriver) throws IOException {
        Screenshot fpScreenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000))
                .takeScreenshot(webDriver);

        BufferedImage originalImage = fpScreenshot.getImage();

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(originalImage, "png", baos);
            baos.flush();
            return baos.toByteArray();
        }
    }
Tizzy answered 20/3, 2019 at 2:26 Comment(1)
Outdated. Do not use this any more - very slow. See the below solutions which work for Firefox and Chrome which did not exist back when this library had been created.Moritz
M
5

Here is a way to use DevTools + Chromedriver to do it:

  private String takeScreenshot(ChromeDriver driver, boolean fullscreen) {
    if (fullscreen) {
      Map<String, Object> layoutMetrics = driver.executeCdpCommand("Page.getLayoutMetrics", Collections.emptyMap());
      Map<String, Object> screenshotConfig = Maps.newHashMap();
      screenshotConfig.put("captureBeyondViewport", true);
      screenshotConfig.put("fromSurface", true);
      Map contentSize = (Map)layoutMetrics.get("contentSize");
      screenshotConfig.put("clip", ImmutableMap.of(
          "width", contentSize.get("width"),
          "height", contentSize.get("height"),
          "x", 0,
          "y", 0,
          "scale", 1
      ));
      Map<String, Object> base64PngResult = driver.executeCdpCommand("Page.captureScreenshot", screenshotConfig);
      return (String)base64PngResult.get("data");
    }
    return driver.getScreenshotAs(OutputType.BASE64);
  }
Moritz answered 21/5, 2022 at 16:25 Comment(0)
J
4

I have found a tutorial http://www.softwaretestingmaterial.com/how-to-capture-full-page-screenshot-using-selenium-webdriver/ For maven users: remember about adding dependendency from https://mvnrepository.com/artifact/ru.yandex.qatools.ashot/ashot When I testing this script, I've got large pictures, which can't be open in browser (too large or broken).

So maybe someone know any script, which focus page on last used locator?

Jeri answered 26/10, 2017 at 5:51 Comment(1)
This code is not working properly in Angujar js applicationOrphrey
T
4

Here is my sample of get Full Screen ScreenShot using C#, but just change:

string _currentPath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(One of your objects)).Location) + @"\Attachs\";
var filePath = _currentPath + sSName;

if (!Directory.Exists(_currentPath))
    Directory.CreateDirectory(_currentPath);

Dictionary<string, Object> metrics = new Dictionary<string, Object>();
metrics["width"] = _driver.ExecuteScript("return Math.max(window.innerWidth,document.body.scrollWidth,document.documentElement.scrollWidth)");
metrics["height"] = _driver.ExecuteScript("return Math.max(window.innerHeight,document.body.scrollHeight,document.documentElement.scrollHeight)");
metrics["deviceScaleFactor"] = (double)_driver.ExecuteScript("return window.devicePixelRatio");
metrics["mobile"] = _driver.ExecuteScript("return typeof window.orientation !== 'undefined'");
_driver.ExecuteChromeCommand("Emulation.setDeviceMetricsOverride", metrics);

_driver.GetScreenshot().SaveAsFile(filePath, ScreenshotImageFormat.Png);

_driver.ExecuteChromeCommand("Emulation.clearDeviceMetricsOverride", new Dictionary<string, Object>());
_driver.Close();
Trochal answered 11/6, 2019 at 1:28 Comment(0)
I
3

It is possible to start Chrome in headless mode and then set the window size to the same height of the page body.

Since the height of your headless browser is not dependent on your monitor size you can use this headless mode to get full length screenshots as they are rendered in the Chrome browser.

The top answer for Headless Chrome run with selenium seems to show the right way to start Chrome in headless mode with java. I work with python bindings but the answer looks pretty similar to what I do.

This is the relevant part. This code should go before you start an instance of ChromeDriver.

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--headless");

ChromeDriver driver = new ChromeDriver(chromeOptions);

If running chrome in a headless browser is not a viable option then you'll have to use Firefox or IE. Both of these browsers will give you a full length screenshot

Inhospitable answered 22/1, 2020 at 16:50 Comment(0)
C
2

Java code without using third party library:

int bodyHeight = webDriver.findElement(By.tagName("body")).getSize().getHeight();
int windowChromeHeight = (int) (long) webDriver.executeScript("return window.outerHeight - window.innerHeight");
Dimension size = new Dimension(webDriver.manage().window().getSize().getWidth(), bodyHeight + windowChromeHeight);
webDriver.executeScript("window.scrollTo(0, 0);");
webDriver.manage().window().setSize(size);
            
File screenshotFile = new File("screenshot.png");
Files.write(screenshotFile.toPath(), webDriver.getScreenshotAs(OutputType.BYTES));
Cleotildeclepe answered 6/12, 2020 at 20:17 Comment(0)
J
1

For some pages I neeed to take screenshot of begin and end of page. So I use to take 2 screenshots:

public static String javaIoTmpDir = System.getProperty("java.io.tmpdir"); //tmp dir
//create screenshot
    driver.manage().window().fullscreen();
    //For large pages - body over 850 px highh - take addition screenshot of the end of page
    if (driver.findElements(By.id("panel_body")).size()>0) {
        WebElement body = driver.findElement(By.id("panel_body"));
        int bodyHight = body.getSize().getHeight();
        if (bodyHight > 850) {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_END);
            robot.keyRelease(KeyEvent.VK_END);
            Thread.sleep(1000);
            File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            String timePictureEnd = javaIoTmpDir+"\\scr_"+String.valueOf(System.currentTimeMillis())+getClass().toString().substring(getClass().toString().lastIndexOf(".qa.")+3)+".png";
            FileUtils.copyFile(scrFile, new File(timePictureEnd));
            robot.keyPress(KeyEvent.VK_HOME); //back to top page for next screen
            robot.keyRelease(KeyEvent.VK_HOME);
            Thread.sleep(1000);
        }
    }
    String timePicture = javaIoTmpDir+"\\scr_"+String.valueOf(System.currentTimeMillis())+getClass().toString().substring(getClass().toString().lastIndexOf(".qa.")+3)+".png";
    File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(scrFile, new File(timePicture));
Jeri answered 15/11, 2017 at 14:31 Comment(0)
C
1

You can use Phantomjs to achieve it.

Here is my java code:

public class PhantomjsTest {
    public static void main(String[] args) {
        try {

            long start=System.currentTimeMillis();
            //The page you want to screenshot
            String targetUrl="https://www.iqiyi.com/";
            //File path
            String targetImg="iqiyi.png";
            String command = "/Users/hetiantian/SoftWares/phantomjs/bin/phantomjs /Users/hetiantian/SoftWares/phantomjs/examples/rasterize.js "+targetUrl + " " +targetImg;
            Process p = Runtime.getRuntime().exec(command);
            p.waitFor();
            System.out.println((System.currentTimeMillis()-start));
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

So you can get a screenshot of full webpage by Phantomjs. When you use Phantomjs to get a full screenshot, you need to download Phantomjs first. Then run Phantomjs script to screenshot. More about it you can reference phantomjs.org.

Commixture answered 28/9, 2018 at 6:5 Comment(2)
@Pierre.Vriens Sorry, my English is not good. What I want to express is you can get screenshot of full webpage by Phantomjs. When you use Phantomjs to get a full screenshot, you need to download Phantomjs first.Then run Phantomjs script to screenshot. More about it you can reference phantomjs.orgCommixture
PhantomJS has been abandoned for at least two years, and officially archived since early 2018. Stop using software that is end-of-life, or which lacks proper support. Also, since --headless switch for Chrome & the extensive Chromium efforts put into headless browsers, third-party projects like PhantomJS have become obsolete, thus the project being abandoned...Episode
H
0

None of the options described here worked for me in my environment (go lang, chromedriver, fedesog implementation of web driver) What came to me eventually is zoom out! This approach can work for pages which are not too long, in which zooming out makes sense.

I think this may be relevant for java or any other language using selenium, so posting it here for anyone who comes across this issue in any programming language :) The following javascript code snippet allows to set zoom level:

document.body.style.zoom = '0.5'

Where 0.5 is the zoom level you want. It can be calculated dynamically based on actual page size, which can be retrieved using:

document.body.scrollHeight

and

document.body.scrollWidth

like mentioned above, and executed like:

webDriver.executeScript(...)

in java or

session.ExecuteScript(...)

in golang using fedesog or similar webdriver framework

Herbertherbicide answered 25/8, 2022 at 9:14 Comment(0)
S
0

This is the simplest solution I found, which I guess should work most of the times:

In headless mode, you can set the viewport to virtually any size you want, indepedent from any existing physical screen size. For example:

    final ChromeOptions options = new ChromeOptions().setHeadless(true).addArguments("window-size=1200,3000");
    driver = new RemoteWebDriver(remoteAddress, options);

Note that you can use a large heights to try and fit the whole page.

Slowly answered 26/1, 2023 at 16:37 Comment(0)
A
0

I'm using Selenium with Chrome Driver in headless mode, and after investigating a lot, I solved this issue with two lines.

First one to change the screen size that is 800x600 by default:

options.add_argument('--window-size=1920,1200')

And I also used this line to apply some zoom out before taking the screenshot:

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

Take into account that this lines are ruby code using Selenium, adapt it to your language.

Asteriated answered 13/12, 2023 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.