Article

How to Take Website Screenshots With Java

·
Vikram Aruchamy
·
11 min read

As a Java programmer, there are many times that you may want to take a screenshot programmatically. For example, when writing automation tests, you may want to take screenshots to store and evaluate the test results. Other use cases could include saving an image of dynamic, user-generated web pages, or monitoring pages that have used your own brand’s assets to showcase a product.

In this tutorial, you'll learn how to take screenshots in Java using different methods. You’ll learn how to create a Java project, and set up an application that can be used to take screenshots of websites programmatically.

Taking Screenshots With Java

You'll need a few things to follow along with this tutorial.

Sign up for a Urlbox account—the free trial is fine. Once you've registered your account, go to your Urlbox user dashboard, and make a note of your API key and API secret, as shown below.

Urlbox dashboard.

You'll also need an IDE for Java. The examples here use the IntelliJ IDEA community version, but you can use any IDE you want.

Finally, you'll need the URL of the website you'd like a screenshot of.

You can find the code used in this article in this GitHub repository.

Setting Up the Demo Project

For this tutorial we are using Java version 12, so make sure you have a JRE installed on your machine JRE Installation Guide.

Open IntelliJ, then click on a New Project, then select Maven.

Java new Maven project.

  • Click Next, then add the GroupId and the ArtifactId, then click on Finish.
Adding the GroupId and ArtifactId

Once you've done that, you should have a basic project structure with default settings.

Default project structure

In the Java project you've just created, create new packages named services’ and main’. The package will be used to create a group of related classes.

To create a package, right-click on the java folder, go to New, and then Package.

Adding new package

This completes the basic project setup.

Basic project setup completed

Taking a Screenshot Using Selenium With the Chrome Driver

Selenium is an open source project for a range of tools. It helps you create robust, browser-based automation tests. It’s commonly used by quality assurance engineers, who write scripts for automating application tests rather than doing the work manually.

We will be using Selenium with the Chrome driver to open a website URL in a browser programmatically, take a screenshot, then close the browser.

To start using Selenium, add the following maven dependencies to your pom.xml:

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.42.2</version>
<scope>compile</scope>
</dependency>
 

Once added, the dependencies should start to download automatically. In order to open the browser programmatically and use Selenium library to interact with it, you'll need to install the following:

Choose a Chrome driver version that is compatible with your Chrome browser version.

To make things easier for this tutorial, you can put your Chrome driver at the root of your project directory under ‘screenshot-java’.

Create the class UrlSelenium under the package services, and copy-paste the code below. This class will contain the methods that will be used to take a screenshot using Selenium and the Chrome driver.

package services;
 
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
 
public class UrlSelenium {
   private int screenshotNum=0;
   private WebDriver driver=null;
 
   public UrlSelenium(int screenshotNum, WebDriver driver) {
       this.driver = driver;
       this.screenshotNum = screenshotNum;
   }
   public void initDriver()
     {
          System.setProperty("webdriver.chrome.driver", "chromedriver");
          this.driver=new ChromeDriver();
          this.driver.manage().window().setPosition(new Point(-2000, 0));
     }
 
     public void capture(String site) throws IOException
     {
          this.screenshotNum++;
          this.driver.get(site);
          File scrFile = ((TakesScreenshot)this.driver).getScreenshotAs(OutputType.FILE);
          FileUtils.copyFile(scrFile, new File("selenium-"+screenshotNum+".png"));
          System.out.println("Took Screenshot for "+site+" and saved as "+"site"+screenshotNum+".png");
     }
 
     public void destroy()
     {
          this.driver.quit();
     }
}
 

In the above code, we have the following methods:

  • initDriver(): A function that will initiate the Chrome driver by creating a new instance of ChromeDriver() and setting its position.
  • capture(String site): A function that takes the site URL as input, then generates a screenshot image of the selected site and saves it into the root directory of the project.
  • destroy(): A function that stops the Chrome driver from running.

Create the class ScreenShotCaptureSelenium under the package main, and copy-paste the code below. This class contains the main method that will take the screenshot using Selenium.

package main;
import java.io.IOException;
import services.UrlSelenium;
import org.openqa.selenium.WebDriver;
 
public class ScreenShotCaptureSelenium {
   static int screenshotNum=0;
   static WebDriver driver=null;
   public static void main(String[] args) throws IOException {
       UrlSelenium selenium = new UrlSelenium(0, null);
       selenium.initDriver();
       selenium.capture("https://www.google.com");
       selenium.capture("https://facebook.com");
       selenium.destroy();
     }
}

The code above does the following :

  • Creates a new instance of our class UrlSelenium.
  • Initiates the chrome driver.
  • Take two screenshots, one of Google and one of Facebook.
  • Stop the Chrome driver.

Now, run the above main class by right-clicking and selecting Run. You will notice that after IntelliJ compiles the code, screenshot images of Google and Facebook get generated under your project directory. The screenshots look like this:

Screenshot of Google Screenshot of Facebook

While these screenshots look fine, taking a screenshot of a scrollable page might be tricky using Selenium, as would getting an effective screenshot of a page that had popups or cookie banners. Selenium isn't an out-of-the-box solution, and while you could customize the output, it would require significantly more resources and development to do so.

Taking a Screenshot Using GrabzIt

GrabzIt is a tool that enables companies to capture screenshots from URLs and convert them into images, PDFs, .docx files, CSV files, and more. The tool features an API that you can use in your application to generate screenshots.

To start using GrabzIt, add the following maven dependencies to your pom.xml:

<dependency>
   <groupId>it.grabz.grabzit</groupId>
   <artifactId>grabzit</artifactId>
   <version>3.5.2</version>
</dependency>
<dependency>
   <groupId>com.sun.xml.bind</groupId>
   <artifactId>jaxb-core</artifactId>
   <version>2.3.0.1</version>
</dependency>
<dependency>
   <groupId>javax.xml.bind</groupId>
   <artifactId>jaxb-api</artifactId>
   <version>2.3.1</version>
</dependency>
<dependency>
   <groupId>com.sun.xml.bind</groupId>
   <artifactId>jaxb-impl</artifactId>
   <version>2.3.1</version>
</dependency>
<dependency>
   <groupId>org.javassist</groupId>
   <artifactId>javassist</artifactId>
   <version>3.25.0-GA</version>
</dependency>

Once added, the dependencies should start to download automatically. Go to the GrabzIt website and create a new account, then sign in to your account. Navigate to Documentation, and scroll down to get your API key and API secret.

GrabzIt credentials

Create the class ScreenShotGrabzIt under the package main, and copy-paste the code below. This class contains the main method that will take the screenshot using GrabzIt.

Run the above main class by right-clicking it, then selecting Run. You will notice that after IntelliJ compiles the code, a screenshot of Tesla's website will appear in your project directory.

GrabzIt image result

As you can see, this probably isn't quite what you'd hoped to capture. The location selection list is foregrounded, and the rest of the page is unreadable.

Additionally, if you want to take a full-page screenshot using GrabzIt, you'll find that it's fairly tricky—you can’t do it dynamically without knowing the dimensions of the page you're trying to screenshot, as shown below:

package main;
 
import it.grabz.grabzit.GrabzItClient;
import it.grabz.grabzit.parameters.ImageOptions;
 
public class ScreenShotGrabzIt {
 
   // main method demos Example Usage of GrabzIt
   public static void main(String[] args) throws Exception {
       GrabzItClient grabzIt = new GrabzItClient("Your Application Key", "Your Application Secret");
       ImageOptions options = new ImageOptions();
       options.setBrowserHeight(1200);
       options.setBrowserWidth(1200);
       grabzIt.URLToImage("https://www.tesla.com", options);
       //Then call the Save or SaveTo method
       grabzIt.SaveTo("tesla-grabzIt.jpg");
   }
}
 

Taking a Screenshot Using Urlbox

Urlbox is a simple and focused website screenshot API. It supports full-page screenshots as a single image, and responsive screenshots that allow you to simulate different screen sizes—it even allows you to pass a user-agent string to take a screenshot of mobile-optimized sites. You can fine tune the look of your screenshots by blocking specific sections, dismissing cookie banners, and blocking popups and ads.

When using the Urlbox API, there's no need to write a single line of JavaScript, or to deploy and maintain a Node application.

Create the Java class ScreenShotUrlBox under the main package that will contain the main method. Under the services package, create the Urlbox class, where you'll define the utility methods that generate the URL. Copy and paste the below code inside the Urlbox class:

package services;
 
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
 
public class UrlBox {
   private String urlboxKey;
   private  String urlboxSecret;
 
   public UrlBox(String urlboxKey, String urlboxSecret) {
       this.urlboxKey = urlboxKey;
       this.urlboxSecret = urlboxSecret;
   }
 
   public String generateUrl(String url, Map<String, Object> options) throws UnsupportedEncodingException {
 
       String encodedUrl = URLEncoder.encode(url, "UTF-8");
       String queryString = String.format("url=%s", encodedUrl);
 
       for (Map.Entry<String, Object> entry : options.entrySet()) {
           String queryParam = "&" + entry.getKey() + "=" + entry.getValue();
           queryString += queryParam;
       }
 
       String token = generateToken(queryString, this.urlboxSecret);
 
       String result = String.format("https://api.urlbox.io/v1/%s/%s/png?%s", this.urlboxKey, token, queryString);
 
       //System.out.println(result);
 
       return result;
   }
 
   private String generateToken(String input, String key) {
       StringBuilder lSignature = new StringBuilder();
       try {
           final Mac lMac = Mac.getInstance("HmacSHA1");
           final SecretKeySpec lSecret = new SecretKeySpec(key.getBytes(), "HmacSHA1");
           lMac.init(lSecret);
           final byte[] lDigest = lMac.doFinal(input.getBytes());
           // final StringBuilder lSignatureBuilder = new StringBuilder();
           for (byte b : lDigest) {
               lSignature.append(String.format("%02x", b));
           }
           return lSignature.toString().toLowerCase();
       } catch (NoSuchAlgorithmException lEx) {
           throw new RuntimeException("Problems calculating HMAC", lEx);
       } catch (InvalidKeyException lEx) {
           throw new RuntimeException("Problems calculating HMAC", lEx);
       }
   }
};
 

Urlbox's API accepts different options to customize the screenshot. Some of the options are width, height, thumb_width, full_page, block_ads, and block_cookie_banners. These options are passed in a map with a key-value pair.

You can use the URL that you’d like a screenshot of and the options map to generate the API URL.

Below are the details about the steps involved in the generateURL() method

To make sure the website URL contains valid characters, we need to encode it into UTF-8 format. Some URLs, especially when they're search results, include special characters in the URL. By encoding the URL, you'll convert these special strings into a valid URL format that the browser can resolve. After encoding, we need to prepend the key url= to the encoded URL.

Use a for loop’ to iterate through the options map and create a query parameter string for our options. For example, thumb_width=240&full_page=true&width=1280 &force=false&height=1024`. These parameters will be injected to the URL so that when we make the API call to the Urlbox provider, it will be able to identify what we have selected.

Once the query string is available, you need to generate a unique token using the query string and the API secret key. The utility method generateToken() generates the token to authenticate the request to the Urlbox API using the utility methods available in the javax.crypto package. This is done to check the integrity of information transmitted over an unreliable medium based on a secret key.

To generate the full API URL, you need the following information:

  • The Urlbox base URL, which is https://api.urlbox.io/v1/
  • Key
  • Token
  • Desired screenshot format, such as PNG or JPG
  • Query string

A URL can be generated in this format using String.format("https://api.urlbox.io/v1/%s/%s/png?%s", this.urlboxKey, token, queryString);. Now you have a valid URL that can be assigned to sources where the screenshot image needs to be stored.

The class ScreenShotUrlBox is where the screenshot taking process lives. Copy and paste the below code inside the ScreenShotUrlBox class under the main package:

package main;
import services.UrlBox;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
 
public class ScreenShotUrlBox {
   // main method demos Example Usage
   public static void main(String[] args) {
       String urlboxKey = "Add You Key Here";
       String urlboxSecret = "Add Your Secret Here";
 
       // Set request options
       Map<String, Object> options = new HashMap<String, Object>();
       options.put("width", 1280);
       options.put("height", 1024);
       options.put("thumb_width", 240);
       options.put("full_page", "true");
       options.put("force", "false");
 
       // Create URL box object with API key and secret
       UrlBox urlbox = new UrlBox(urlboxKey, urlboxSecret);
       try {
           // Call generateUrl function of urlbox object
           String urlboxUrl = urlbox.generateUrl("https://draft.dev", options);
           // Now do something with urlboxUrl.. put in an img tag, etc..
           System.out.println(urlboxUrl);
           //save image locally
           try (InputStream in = new URL(urlboxUrl).openStream()) {
           Files.copy(in, Paths.get("draft-urlBox.png"));
           } catch (MalformedURLException e) {
               e.printStackTrace();
           } catch (IOException e) {
               e.printStackTrace();
           }
       } catch (UnsupportedEncodingException ex) {
           throw new RuntimeException("Problem with url encoding", ex);
       }
   }
}
 

The above code goes through the following steps to take a screenshot:

  • Defines the Urlbox API key and the API secret key.
  • Sets request options in a map as a key-value format.
  • Creates an instance of type Urlbox, then invokes the generateURL() method with the desired URL and options map. The resultant URL will contain a valid API URL.
  • Stores the screenshot locally, which will be stored by default under your main project directory.

Now, run the above main class by right-clicking and selecting Run. You'll notice that after IntelliJ compiles the code, a screenshot of the full webpage will be saved in your project directory.

Urlbox image result

Conclusion

In this tutorial, you've created several simple Java programs using tools like Selenium, GrabzIt, and Urlbox to take screenshots programmatically. UrlBox stands out from tools like Selenium and GrabzIt because it also offers out-of-the-box features such as high-DPI images that look great on retina screens, popup blocking, automatic dismissal of cookie banners to prevent them spoiling your screenshots, ad blocking, and automatic CAPTCHA bypass.

Handling issues like this with other tools is time-consuming and costly, and requires writing extensive custom code—if it's possible at all.

Urlbox is a fast and accurate screenshot rendering service at scale. It offers many options, such as blocking ads and popups, or even changing the appearance of a page with custom CSS or JavaScript. If you need a seamless screenshot solution that integrates into your workflow, give Urlbox a try.