---
title: "Parsing HTML With Java and jsoup"
slug: parse-html-with-jsoup
date: 2025-02-06T13:55:56+00:00
modified: 2025-09-16T16:37:37+00:00
permalink: https://brightdata.com/blog/web-data/parse-html-with-jsoup
type: blog
---

[ Blog ](https://brightdata.com/blog "Blog") / [Web Data](https://brightdata.com/blog/web-data)







 [Web Data](https://brightdata.com/blog/web-data)

# Parsing HTML With Java and jsoup

Master HTML parsing with jsoup in Java. Learn DOM methods, handle pagination, and optimize your parsing workflow with this detailed guide.

 2 min read





 [ ](https://brightdata.com/blog/authors/jake-nulty)

 [Jake Nulty

Technical Writer

 ](https://brightdata.com/blog/authors/jake-nulty)





 ![Parsing HTML With Java and Jsoup blog image](https://media.brightdata.com/2025/02/Parsing-HTML-With-Java-and-Jsoup.svg)





When you scrape the web, HTML parsing is vital no matter which tools you’re using. [Web scraping with Java](/blog/how-tos/java-web-scraping) is no exception to this rule. In Python, we use tools like [Requests](/blog/web-data/python-requests-guide) and [BeautifulSoup](/blog/how-tos/beautiful-soup-web-scraping). With Java, we can send our HTTP requests and parse our HTML using [jsoup](https://jsoup.org/). We’ll use [Books to Scrape](https://books.toscrape.com/) for this tutorial.

## Getting Started

In this tutorial, we’re going to use Maven for dependency management. If you don’t already have it, you can install Maven [here](https://maven.apache.org/install.html).

Once you’ve got Maven installed, you need to create a new Java project. The command below creates a new project, `jsoup-scraper`.

```none
mvn archetype:generate -DgroupId=com.example -DartifactId=jsoup-scraper -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

```

Next, you’ll need to add relevant dependencies. Replace the code in `pom.xml` with the code below. This is similar to dependency management in [Rust](/blog/how-tos/web-scraping-with-rust) with Cargo.

```none
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>jsoup-scraper</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>jsoup-scraper</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.16.1</version>
    </dependency>
  </dependencies>
  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

```

Go ahead and paste the following code into `App.java`. It’s not much, but this is the basic scraper we’ll build from.

```none
package com.example;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

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

        String url = "https://books.toscrape.com";
        int pageCount = 1;

        while (pageCount <= 1) {

            try {
                System.out.println("---------------------PAGE "+pageCount+"--------------------------");

                //connect to a website and get its HTML
                Document doc = Jsoup.connect(url).get();

                //print the title
                System.out.println("Page Title: " + doc.title());


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("Total pages scraped: "+(pageCount-1));
    }
}

```

- `Jsoup.connect("https://books.toscrape.com").get()`: This line fetches the page and returns a `Document` object that we can manipulate.
- `doc.title()` returns the title in the HTML document, in this case: `All products | Books to Scrape - Sandbox`.

## <a></a>Using DOM Methods With Jsoup

jsoup contains a variety of methods for finding elements in the DOM(Document Object Model). We can use any of the following to find page elements easily.

- `getElementById()`: Find an element using its `id`.
- `getElementsByClass()`: Find all elements using their CSS class.
- `getElementsByTag()`: Find all elements using their HTML tag.
- `getElementsByAttribute()`: Find all elements containing a certain attribute.

### <a></a>getElementById

On our target site, the sidebar contains a `div` with an `id` of `promotions_left`. You can see this in the image below.

```none
//get by Id
Element sidebar = doc.getElementById("promotions_left");

System.out.println("Sidebar: " + sidebar);

```

This code outputs the HTML element you see in the inspect page.

```none
Sidebar: <div id="promotions_left">
</div>

```

### <a></a>getElementsByTag

`getElementsByTag()` allows us to find all elements on the page with a certain tag. Let’s look at the books on this page.

Each book is contained in a unique `article` tag.

The code below won’t print anything, but it will return an array of books. These books will provide the basis for the rest of our data.

```none
//get by tag
Elements books = doc.getElementsByTag("article");

```

### <a></a>getElementsByClass

Let’s look at the price of a book. As you can see hightlighted, its class is `price_color`.

In this snippet, we find all elements of the `price_color` class. We then print the text of the first one using `.first().text()`.

```none
System.out.println("Price: " + book.getElementsByClass("price_color").first().text());

```

### <a></a>getElementsByAttribute

As you might already know, all `a` elements require an `href` attribute. In the code below, we use `getElementsByAttribute("href")` to find all elements with an `href`. We use `.first().attr("href")` to return its `href`.

```none
//get by attribute
Elements hrefs = book.getElementsByAttribute("href");
System.out.println("Link: https://books.toscrape.com/" + hrefs.first().attr("href"));

```

## <a></a>Advanced Techniques

### <a></a>CSS Selectors

When we want to use multiple criteria to find elements, we can pass [CSS selectors](/blog/web-data/xpath-vs-css-selectors) into the `select()` method. This method returns an array of all objects matching the selector. Below, we use `li[class='next']` to find all `li` items with the `next` class.

```none
Elements nextPage = doc.select("li[class='next']");

```

### <a></a>Handling Pagination

To handle our pagination, we use `nextPage.first()` to call `getElementsByAttribute("href").attr("href")` on the first element returned from the array and extract its `href`. Interestingly enough, after page 2, the word `catalogue` gets removed from the links, so if it isn’t present in the `href`, we add it back in. We then combine this link with our base url and use it to get the link to the next page.

```none
if (!nextPage.isEmpty()) {
    String nextUrl = nextPage.first().getElementsByAttribute("href").attr("href");
    if (!nextUrl.contains("catalogue")) {
        nextUrl = "catalogue/"+nextUrl;
    }
    url = "https://books.toscrape.com/" + nextUrl;
    pageCount++;
}

```

## <a></a>Putting Everything Together

Here is our final code. If you wish to scrape more than one page, simply change the `1` in `while (pageCount <= 1)` to your desired target. If you want to scrape 4 pages, use `while (pageCount <= 4)`.

```none
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

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

        String url = "https://books.toscrape.com";
        int pageCount = 1;

        while (pageCount <= 1) {

            try {
                System.out.println("---------------------PAGE "+pageCount+"--------------------------");

                //connect to a website and get its HTML
                Document doc = Jsoup.connect(url).get();

                //print the title
                System.out.println("Page Title: " + doc.title());

                //get by Id
                Element sidebar = doc.getElementById("promotions_left");

                System.out.println("Sidebar: " + sidebar);

                //get by tag
                Elements books = doc.getElementsByTag("article");

                for (Element book : books) {
                    System.out.println("------Book------");
                    System.out.println("Title: " + book.getElementsByTag("img").first().attr("alt"));
                    System.out.println("Price: " + book.getElementsByClass("price_color").first().text());
                    System.out.println("Availability: " + book.getElementsByClass("instock availability").first().text());

                    //get by attribute
                    Elements hrefs = book.getElementsByAttribute("href");
                    System.out.println("Link: https://books.toscrape.com/" + hrefs.first().attr("href"));
                }

                //find the next button using its CSS selector
                Elements nextPage = doc.select("li[class='next']");
                if (!nextPage.isEmpty()) {
                    String nextUrl = nextPage.first().getElementsByAttribute("href").attr("href");
                    if (!nextUrl.contains("catalogue")) {
                        nextUrl = "catalogue/"+nextUrl;
                    }
                    url = "https://books.toscrape.com/" + nextUrl;
                    pageCount++;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("Total pages scraped: "+(pageCount-1));
    }
}

```

Before you run the code, remember to compile it.

```none
mvn package

```

Then run it with the following command.

```none
mvn exec:java -Dexec.mainClass="com.example.App"

```

Here is the output from the first page.

```none
---------------------PAGE 1--------------------------
Page Title: All products | Books to Scrape - Sandbox
Sidebar: <div id="promotions_left">
</div>
------Book------
Title: A Light in the Attic
Price: £51.77
Availability: In stock
Link: https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html
------Book------
Title: Tipping the Velvet
Price: £53.74
Availability: In stock
Link: https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html
------Book------
Title: Soumission
Price: £50.10
Availability: In stock
Link: https://books.toscrape.com/catalogue/soumission_998/index.html
------Book------
Title: Sharp Objects
Price: £47.82
Availability: In stock
Link: https://books.toscrape.com/catalogue/sharp-objects_997/index.html
------Book------
Title: Sapiens: A Brief History of Humankind
Price: £54.23
Availability: In stock
Link: https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html
------Book------
Title: The Requiem Red
Price: £22.65
Availability: In stock
Link: https://books.toscrape.com/catalogue/the-requiem-red_995/index.html
------Book------
Title: The Dirty Little Secrets of Getting Your Dream Job
Price: £33.34
Availability: In stock
Link: https://books.toscrape.com/catalogue/the-dirty-little-secrets-of-getting-your-dream-job_994/index.html
------Book------
Title: The Coming Woman: A Novel Based on the Life of the Infamous Feminist, Victoria Woodhull
Price: £17.93
Availability: In stock
Link: https://books.toscrape.com/catalogue/the-coming-woman-a-novel-based-on-the-life-of-the-infamous-feminist-victoria-woodhull_993/index.html
------Book------
Title: The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics
Price: £22.60
Availability: In stock
Link: https://books.toscrape.com/catalogue/the-boys-in-the-boat-nine-americans-and-their-epic-quest-for-gold-at-the-1936-berlin-olympics_992/index.html
------Book------
Title: The Black Maria
Price: £52.15
Availability: In stock
Link: https://books.toscrape.com/catalogue/the-black-maria_991/index.html
------Book------
Title: Starving Hearts (Triangular Trade Trilogy, #1)
Price: £13.99
Availability: In stock
Link: https://books.toscrape.com/catalogue/starving-hearts-triangular-trade-trilogy-1_990/index.html
------Book------
Title: Shakespeare's Sonnets
Price: £20.66
Availability: In stock
Link: https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html
------Book------
Title: Set Me Free
Price: £17.46
Availability: In stock
Link: https://books.toscrape.com/catalogue/set-me-free_988/index.html
------Book------
Title: Scott Pilgrim's Precious Little Life (Scott Pilgrim #1)
Price: £52.29
Availability: In stock
Link: https://books.toscrape.com/catalogue/scott-pilgrims-precious-little-life-scott-pilgrim-1_987/index.html
------Book------
Title: Rip it Up and Start Again
Price: £35.02
Availability: In stock
Link: https://books.toscrape.com/catalogue/rip-it-up-and-start-again_986/index.html
------Book------
Title: Our Band Could Be Your Life: Scenes from the American Indie Underground, 1981-1991
Price: £57.25
Availability: In stock
Link: https://books.toscrape.com/catalogue/our-band-could-be-your-life-scenes-from-the-american-indie-underground-1981-1991_985/index.html
------Book------
Title: Olio
Price: £23.88
Availability: In stock
Link: https://books.toscrape.com/catalogue/olio_984/index.html
------Book------
Title: Mesaerion: The Best Science Fiction Stories 1800-1849
Price: £37.59
Availability: In stock
Link: https://books.toscrape.com/catalogue/mesaerion-the-best-science-fiction-stories-1800-1849_983/index.html
------Book------
Title: Libertarianism for Beginners
Price: £51.33
Availability: In stock
Link: https://books.toscrape.com/catalogue/libertarianism-for-beginners_982/index.html
------Book------
Title: It's Only the Himalayas
Price: £45.17
Availability: In stock
Link: https://books.toscrape.com/catalogue/its-only-the-himalayas_981/index.html
Total pages scraped: 1

```

## <a></a>Conclusion

Now that you’ve learned how to extract HTML data using jsoup, you can start building more advanced web scrapers. Whether you’re scraping product listings, news articles, or research data, handling dynamic content and avoiding blocks are key challenges.

To scale your scraping efforts efficiently, consider using Bright Data’s tools:

- **[Residential Proxies](/proxy-types/residential-proxies)** – Avoid IP bans and access geo-restricted content.
- **[Scraping Browser](/products/scraping-browser)** – Render JavaScript-heavy sites effortlessly.
- **[Ready-to-Use Datasets](/products/datasets)** – Skip scraping altogether and get structured data instantly.

By combining jsoup with the right infrastructure, you can extract data at scale while minimizing detection risks. Ready to take your web scraping to the next level? Sign up now and start your free trial.



Contact usStart free trial

No credit card required











 [ ](https://www.linkedin.com/in/jacob-nulty-682803187/)

Jake Nulty

 Technical Writer



  6 years experience



Jacob Nulty is a Detroit-based software developer and technical writer exploring AI and human philosophy, with experience in Python, Rust, and blockchain.



Expertise

  Data Structures   Python   Rust



 [ View all articles ](https://brightdata.com/blog/authors/jake-nulty)











 Table of Contents







Dedicated Scraper APIs &amp; No-Code Scrapers

Over 1000 scrapers for all popular domains. Simplify your web scraping.

[See pricing](/pricing/web-scraper "See pricing")

Just want data? Skip scraping.

Hundreds of ready-to-use datasets from all popular domains.

[See pricing](/pricing/datasets "See pricing")







 [ ](https://news.ycombinator.com/submitlink?t=Parsing+HTML+With+Java+and+jsoup&u=https://brightdata.com/blog/web-data/parse-html-with-jsoup) [ ](https://www.linkedin.com/shareArticle?mini=true&title=Parsing+HTML+With+Java+and+jsoup&url=https://brightdata.com/blog/web-data/parse-html-with-jsoup) [ ](http://www.reddit.com/submit?title=Parsing+HTML+With+Java+and+jsoup&url=https://brightdata.com/blog/web-data/parse-html-with-jsoup)







##  You might also be interested in

 [ ](https://brightdata.com/blog/ai/openhuman-with-bright-data "Production-Ready Web Access in OpenHuman Through the Bright Data CLI")

 [AI





Antonello Zanini

Technical Writer





### Production-Ready Web Access in OpenHuman Through the Bright Data CLI

Integrate Bright Data CLI with OpenHuman to enable production-ready web access and data collection for AI agents.



 09-Sep-2026

 12 min read

 ](https://brightdata.com/blog/ai/openhuman-with-bright-data)

 [ ](https://brightdata.com/blog/ai/minimax-m3-with-bright-data "Giving self-hosted MiniMax M3 agents live web access with Bright Data")

 [AI





Satyam Tripathi

Technical Writer





### Giving self-hosted MiniMax M3 agents live web access with Bright Data

Self-hosted MiniMax M3 agents get live web access using Bright Data’s search and scraping tools. Bypass blocks and CAPTCHAs.



 09-Sep-2026

 54 min read

 ](https://brightdata.com/blog/ai/minimax-m3-with-bright-data)

 [ ](https://brightdata.com/blog/web-data/multimodal-web-scraping-with-minimax "Multimodal Web Scraping with MiniMax")

 [Web Data





Antonello Zanini

Technical Writer





### Multimodal Web Scraping with MiniMax

Pair Bright Data Web Unlocker with MiniMax M3 vision to extract structured data from images and web page screenshots.



 09-Sep-2026

 4 min read

 ](https://brightdata.com/blog/web-data/multimodal-web-scraping-with-minimax)
