How to take full page Screenshot of a scrollable webpage using Selenium WebDriver with Java?
Asked Answered
P

8

7

Existing code which takes screenshot of only visible screen. I am using the Chromedriver.

  System.setProperty("webdriver.chrome.driver", "D:/chromedriver/chromedriver.exe");
  WebDriver driver = new ChromeDriver();
  driver.get("http://www.bbc.com");       
  driver.manage().window().maximize();
  System.out.println(driver.getTitle());
  File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
  FileUtils.copyFile(scrFile, new File("D:/chromedriver/scr3.png"));
  driver.close();
Paolo answered 23/3, 2017 at 10:33 Comment(4)
I guess it can't be possible, because selenium may able to interact with only visible web-elements.Volcano
Can you manually take screenshot of page which are not visible because of scroll bar? Because to view those part of page you manually need to scroll. If not, then how you can achieve it using selenium?Altarpiece
@ShoaibAkhtar selenium IDE has a command (captureEntirePageScreenshot) which takes screenshots of full page (scrollable page) then why it is not possible to implement that in webdriverPaolo
@SarthakSrivastava Will the scroll bar on that image are scroll-able? You want to generate screenshot with scroll bar and you should be able to scroll the scroll bar in that screenshot. This is what is your requirement I guess. If yes, then I think it is not possible even with captureEntirePageScreenshot in Selenium IDE. Or your requirement is something else?Altarpiece
S
3

Please Find the below code, you can scroll and take screenshots as many as you want. Note the elements Webelement. Store them and scroll relatively. You can Scroll depending upon how many screenshots you want.

driver.get("http://www.bbc.com");       
driver.manage().window().maximize();
System.out.println(driver.getTitle());
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:/chromedriver/scr3.png"));  
WebElement elements = driver.findElement(By.xpath(".//*[@id='page']/section[6]/div/div/div[1]/ul/li[3]/div/div[2]/h3/a"));    
Thread.sleep(3000L);
JavascriptExecutor js = (JavascriptExecutor) driver;
int yPosition = elements.getLocation().getY();
js.executeScript("window.scroll (0, " + yPosition + ") ");       
Thread.sleep(3000L);         
File scrFile1 = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile1, new File("D:/chromedriver/scr4.png"));
driver.close();
Schick answered 23/3, 2017 at 11:30 Comment(1)
Have you a solution with one olny png file (merged)?Rorqual
H
3

Using Shutterbug, short and sweet:

public byte[] shootPage() throws IOException {
    BufferedImage image = Shutterbug.shootPage(driver, ScrollStrategy.WHOLE_PAGE).getImage();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    ImageIO.write(image, "png", outputStream);
    return outputStream.toByteArray();
}
Higgs answered 27/4, 2020 at 4:55 Comment(0)
T
1

You can't do this using merely selenium. You need other tool to perform your task. Follow the link and see my answer: Screen shot issue in selenium webdriver

Hope, it may help you.

Theatrics answered 23/3, 2017 at 11:14 Comment(0)
D
1

You Can Try This Method. Hope It Will Be Useful:-

public static void takeFullPageScreenShot(WebDriver driver) throws IOException {

    JavascriptExecutor jsExec = (JavascriptExecutor)driver;

    jsExec.executeScript("window.scrollTo(0, 0);"); //Scroll To Top

    Long innerHeight = (Long) jsExec.executeScript("return window.innerHeight;");
    Long scroll = innerHeight;

    Long scrollHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;"); 

    scrollHeight = scrollHeight + scroll;

    do{

        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        //Unique File Name For Each Screenshot
        File destination = new File("E://screenshots//"+String.join("_", 
        LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+".jpg");

        FileUtils.copyFile(screenshot, destination));

        jsExec.executeScript("window.scrollTo(0, "+innerHeight+");");

        innerHeight = innerHeight + scroll;

    }while(scrollHeight >= innerHeight);
}


Or,
  File screenshot = 
  driver.findElement(By.tagName("body")).getScreenshotAs(OutputType.FILE);
  File destination = new File("E://screenshots//"+String.join("_", 
  LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+".jpg");
  FileUtils.copyFile(screenshot, destination));
Divorce answered 24/1, 2019 at 20:28 Comment(0)
S
1

To take screenshot of a complete webpage, we have to use a third party utility called 'aShot'. aShot is a WebDriver Schreenshot Utility with which we can take screenshot of the entire webpage & also individual WebElement. To do this, we have to download the aShot jar file & add to our project along with Selenium jar files.

Suppression answered 8/2, 2019 at 7:21 Comment(0)
P
1

In Selenium 4, FirefoxDriver provides a getFullPageScreenshotAs method that handles vertical and horizontal scrolling, as well as fixed elements (e.g. navbars). Other drivers do not yet have this functionality.

System.setProperty("webdriver.gecko.driver", "path/to/geckodriver");
final FirefoxOptions options = new FirefoxOptions();
// set options...
final FirefoxDriver driver = new FirefoxDriver(options);
driver.get("https://stackoverflow.com/");
File fullScreenshotFile = driver.getFullPageScreenshotAs(OutputType.FILE);
// File will be deleted once the JVM exits, so you should copy it
Prato answered 16/8, 2021 at 17:37 Comment(0)
R
0

Try this code. The above response by AB D has some logic errors. They are resolved below:

public static void takeFullPageScreenShot(WebDriver driver) throws IOException {

    JavascriptExecutor jsExec = (JavascriptExecutor)driver;

    //Returns a Long, Representing the Height of the window’s content area.
    Long windowHeight = (Long) jsExec.executeScript("return window.innerHeight;");

    //Returns a Long, Representing the Height of the complete WebPage a.k.a. HTML document.
    Long webpageHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;"); 

    //Marker to keep track of the current position of the scroll point
    //Long currentWindowScroll = Long.valueOf(0);
    //Using java's boxing feature to create a Long object from native long value.

    Long currentWindowScroll = 0L;

    do{
        //System.out.println(windowHeight + ", " + webpageHeight + ", " + currentWindowScroll);

        jsExec.executeScript("window.scrollTo(0, " + currentWindowScroll + ");");

        Actions act = new Actions(driver);
        act.pause(5000).perform();

        File tempScreenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        //Unique File Name For Each Screenshot
        File destination = new File("C:\\core_java\\DemoScreenShot\\" + String.join("_", LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+ ".png");

        Files.copy(tempScreenshot, destination);
        currentWindowScroll = currentWindowScroll + windowHeight;

    }while(currentWindowScroll <= webpageHeight);
}
Resume answered 14/5, 2019 at 17:4 Comment(0)
G
0

Here's an advance on @kwishna's answer which stitches the screenshots together into a single image:

    public void takeFullPageScreenShot(WebDriver driver) throws IOException {
        JavascriptExecutor jsExec = (JavascriptExecutor) driver;
        jsExec.executeScript("window.scrollTo(0, 0);");
        Long innerHeight = (Long) jsExec.executeScript("return window.innerHeight;");
        Long scroll = innerHeight;
        Long scrollHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;");

        scrollHeight = scrollHeight + scroll;

        List<byte[]> images = new ArrayList<>();

        do {
            byte[] screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
            images.add(screenshot);
            jsExec.executeScript("window.scrollTo(0, "+innerHeight+");");
            innerHeight = innerHeight + scroll;
        } while (scrollHeight >= innerHeight);

        BufferedImage result = null;
        Graphics g = null;

        int x = 0, y = 0;
        for(byte[] image : images){
            InputStream is = new ByteArrayInputStream(image);
            BufferedImage bi = ImageIO.read(is);
            if (result == null) {
                // Lazy init so we can infer height and width
                result = new BufferedImage(
                        bi.getWidth(), bi.getHeight() * images.size(),
                        BufferedImage.TYPE_INT_RGB);
                g = result.getGraphics();
            }
            g.drawImage(bi, x, y, null);
            y += bi.getHeight();
        }
        ImageIO.write(result,"png",new File("result.png"));
    }
Gesticulative answered 26/11, 2021 at 11:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.