Read QR Code content with Selenium and zxing

Easily read a QR Code and use it in your test

Elias Nogueira
3 min readFeb 16, 2018

The problem

Recently one of my teams faced a technical problem: read a QR Code from a web page to use it for an authorisation process.

As we need to create an E2E test to guarantee the user journey, the main problem is how to read the content of a QR Code, on a webpage, and use it in the subsequent test.

As we use Selenium WebDriver with Java as programming language the main challenge was find a library (in Java) to read the QR Code.

Reading a QR Code

The ZXing (“zebra crossing”) is an open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages. One of supported 2D format is the QR Code.

The first thing we did was add the ZXing library to our project classpath. Bellow the snippet in a pom.xml file (Maven)

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>

After we've created a way to receive an URL and decode the QR Code.
The simple steps are:

  1. Read the URL through Image.IO and pass it to a BufferedImage
  2. Pass the BufferedImage to BufferedImageLuminanceSource Zxing class
  3. Instantiate the class HybridBinarizer, that is responsible to read the 2D barcode (QR Code), with BufferedImageLuminanceSource as parameter and create a new BinaryBitmap, to prepare to decode the 2D barcode
  4. Instantiate a MultiFormatReader calling the decode method passing the BinaryBitmap. The MultiFormatReader is a convenience class and will attempts to decode all barcode formats that the library supports. The result is a Result class that encapsulates the result of decoding a barcode within an image

So we created a function to do all this magic…

private static String decodeQRCode(URL qrCodeImage) throws IOException, NotFoundException {
BufferedImage bufferedImage = ImageIO.read(qrCodeImage);
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

Result result = new MultiFormatReader().decode(bitmap);
return result.getText();
}

How about Selenium?

Now we just need to find the QR Code on the page, through the element image (probably) and get the src attribute.

An example may be found at the github example (in the end of this post). The code bellow is a Selenium snippet to find an element by the id "qr" (and image) and get the attribute src.

String qrCodeFile = driver.findElement(By.id("qr")).getAttribute("src");

The result will be a String with complete image URL (the src attribute content).
E.g: https://eliasnogueira.github.io/selenium-read-qrcode/qrcode.png

After that we just pass this String to decodeQRCode method (the example above) and the result will the QR Code content. In this example the QR Code is a text "QR Code output text".

Voilà! Easily we have a code that read a QR Code image on a webpage!

But, if the QR Code come from a Base64 instead of URL?

A few things in the code will change.

  1. Decode the Base64 String in a array of bytes
  2. Pass the decoded String to ImageIO.read parameter. Here you need to instantiate a new ByteArrayInputStream
  3. The rest of the code don't change

Exemple:

private static String decodeQRCode(String base64QRCode) throws IOException, NotFoundException {byte[] decoded = Base64.decodeBase64(base64Source);
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(base64QRCode));
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

Result result = new MultiFormatReader().decode(bitmap);
return result.getText();
}

Note that I have changed the method decodeQRCode to expect a String parameter.

You can appy some logic to just have one method and try to realize if it's a URL or Base64 String.

The github example

The complete and functional example may be found at https://github.com/eliasnogueira/selenium-read-qrcode

There's just one method to decode the image that figure out if the parameter is a URL or Base64 image and two test to assert this logic.

--

--