How to Scrape Zoopla Property Listings

Tutorial on how to scrape Zoopla

Looking to make better investment decisions and gain a competitive advantage in your market? Then, it’s time for you to start scraping Zoopla to gather the necessary information – like new listings, price trends, etc. – to accomplish your goals.

With millions of properties listed on their platform, Zoopla is a gold mine for real estate analysts.

However, Zoople’s anti-scraping mechanisms, such as CAPTCHA challenges, request rate-limiting, and IP address bans, make it hard to get consistent access to property data at scale.

Collect Property Data from All Major Sites

Get a consistent flow of data from sites like Zoopla, Zillow and Realtor with a simple API call.

In this tutorial, we’ll show you how to build a Zoopla web scraper capable of bypassing its anti-bot protection using Node.js and ScraperAPI to never get blocked again.

TL;DR: Full Zoopla Scraper

For those in a hurry, here is the full Node.js code:

<pre class="wp-block-syntaxhighlighter-code">
	const axios = require('axios');
	const cheerio = require('cheerio');
	
	const ZOOPLA_PAGE_URL = 'https://www.zoopla.co.uk/for-sale/property/liverpool/?q=Liverpool%2C+Merseyside&results_sort=newest_listings&search_source=home';
	const API_URL = 'https://api.scraperapi.com';
	const API_KEY = '<API_KEY>' // <--- Enter your API key here
	
	const webScraper = async () => {
	   console.log('Fetching data with ScraperAPI...');
	
	   const queryParams = new URLSearchParams({
		   api_key: API_KEY,
		   url: ZOOPLA_PAGE_URL,
		   country_code: 'uk'
	   });
	
	   try {
		   const response = await axios.get(`${API_URL}?${queryParams.toString()}`);
	
		   const html = response.data;
	
		   const $ = cheerio.load(html);
		   const propertyList = [];
	
		   console.log('Extracting information from the HTML...');
	
		   $(".dkr2t82").each((_, el) => {
			   const link = $(el).find('a._1lw0o5c2').attr('href');
			   const tagsElement = $(el).find('ul._1ial65f0 li');
			   const configsElement = $(el).find('ul._1wickv0 li');
			   const price = $(el).find('._1egbt4s3r p:last-child').text();
			   const title = $(el).find('h2.m6hnz61').text();
			   const address = $(el).find('address.m6hnz62').text();
			   const description = $(el).find("p.m6hnz63").text();
	
			   const tags = [];
			   const configs = {};
	
			   tagsElement.each((_, el) => {
				   tags.push($(el).text().replaceAll(' ', '_').toLowerCase())
			   })
	
			   configsElement.each((_, el) => {
				   const label = $(el).find('span._1wickv2').text().replaceAll(' ', '_').toLowerCase();
				   const count = $(el).find('span:last-child').text();
	
				   configs[label] = +count;
			   })
	
			   propertyList.push({
				   description,
				   price,
				   title,
				   address,
				   tags,
				   configuration: configs,
				   link: link.startsWith('https') ? link : `https://www.zoopla.co.uk${link}`
			   });
		   });
	
		   console.log('JSON result:', propertyList);
	   } catch (error) {
		   console.log(error)
	   }
	};
	
	void webScraper();
</pre>

Note: Before running this code, install the dependencies and set your API key, which you can find in the ScraperAPI dashboard.

Want to learn how to build this scraper from scratch? Let’s jump into the tutorial!

How to Scrape Zoopla Property Listings

To show you how to scrape Zoopla property data, we’ll write a scraper that finds properties for sale in the city of Liverpool.

For each property for sale, we’ll retrieve the following information:

  • Title
  • Description
  • Address
  • Price
  • Configuration
  • Property URL

The script will return the list of properties in JSON format, so you can easily use it for other purposes.

Showing 2 Results from Zoopla result page

Prerequisites

You must have these tools installed on your computer to follow this tutorial.

Note: Check this tutorial if this is your first time using Node.js for web scraping.

Step 1: Set Up the Project

Let’s create a folder that will contain the source code of the Zoopla Web scraper.


	mkdir zoopla-scraper

Enter the folder and initialize a new Node.js project


	cd zoopla-scraper

	npm init -y	

The second command above will create a package.json file in the folder. Let’s create a file index.js and add a simple JavaScript instruction inside.


	touch index.js

	echo "console.log('Hello world!');" > index.js	

Run the file index.js using the Node.js runtime.


	node index.js

This execution will print the message Hello world! in the terminal.

Step 2: Install the Dependencies

We must install two Node.js packages to build the Zoopla Web scraper:

  • Axios – to build the HTTP request (headers, body, query string parameters, etc.), send it to ScraperAPI, and download the HTML content.
  • Cheerio – to extract the information from the HTML downloaded from the Axios request.

Run the command below to install these packages:


	npm install axios cheerio

Step 3: Identify the DOM Selectors to Target

Navigate to https://www.zoopla.co.uk, the property for sale is the default option. Type “Liverpool” in the search bar and press enter.

When the search result appears listing the properties, inspect the page to display the HTML structure and identify the DOM selector associated with the HTML tag wrapping the information we want to extract.

Identifying Zoopla CSS selector associated with HTML tag

From the above picture, here are all the DOM selectors the Web scraper will target to extract the information of each property.

Information DOM Selector
Title .dkr2t82 h2.m6hnz61
Description .dkr2t82 p.m6hnz63
Price .dkr2t82 ._1egbt4s3r p:last-child
Address .dkr2t82 address.m6hnz62
Property’s configuration .dkr2t82 ul._1wickv0 li
Property’s link .dkr2t82 a._1lw0o5c2

Be careful when writing the selector because a misspelling will prevent the script from retrieving the correct value.

Note: A good method to avoid errors when building your selectors is to try them with jQuery first. In the browser console, type your selector like $(".dkr2t82 h2.m6hnz61") if it returns the correct DOM element, then you are good to go.

Testing Zoopla Selectors with Jquery

Step 4: Scrape Zoopla’s property page

We will use Axios to build the HTTP request to send to the ScraperAPI’s API. The request needs the following query parameters:

  • The URL to scrape: it is the URL of the Zoopla properties search page; you can copy it into the address bar of your browser.
  • The API Key: to authenticate against the Scraping API and perform the scraping; if you still have enough credit, find it on the dashboard page of your ScraperAPI account.
Need Moren Than 3M API Credits per Month?

Custom enterprise plans include +3M API credits, +100 concurrent requests, premium support and an account manager.

Use of geotargeting for Web scraping

Geo-targeting refers to delivering content, advertisements, or services to users based on their geographic location, mainly determined by their IP address.

In the real estate industry, location is one of the most critical factors for property buyers or renters. Using ScraperAPI’s geo-targeting makes scraping Zoopla more precise by allowing us to gather localized information as local searchers would.

With ScraperAPI, you can specify the country code from which the request must be sent. In the HTTP request query parameter, set the key country_code with the value uk to indicate the request comes from the United Kingdom.

Note: Check out the ScraperAPI’s API documentation to view the supported country codes.

Edit the index.js to add the code below that builds the HTTP request, sends it, receives the response, and prints it in the terminal.

<pre class="wp-block-syntaxhighlighter-code">
	const axios = require('axios');

	const ZOOPLA_PAGE_URL = 'https://www.zoopla.co.uk/for-sale/property/liverpool/?q=Liverpool%2C+Merseyside&results_sort=newest_listings&search_source=home';
	const API_URL = 'https://api.scraperapi.com';
	const API_KEY = '<API_KEY>' // <--- Enter your API key here
	
	const webScraper = async () => {
		console.log('Fetching data with ScraperAPI...');
	
		const queryParams = new URLSearchParams({
				api_key: API_KEY,
				url: ZOOPLA_PAGE_URL,
				country_code: 'uk'
		});
	
		try {
				const response = await axios.get(`${API_URL}?${queryParams.toString()}`);
	
				const html = response.data;
	
				console.log("HTML content", html);
		} catch (error) {
				console.log(error)
		}
	};
	
	void webScraper();
</pre>

Note: Don’t have an API key yet? Create a free ScraperAPI account and get 5,000 API credits, plus access to all our tools.

Step 5: Extract Zoopla Property Details

Now that we have the HTML content of the page, let’s parse it with Cheerio to easily navigate through the DOM and extract all the information we want.

Cheerio provides functions to load HTML text, then navigate through the structure to extract information using the DOM selectors.

The code below goes through each element, extracts the information, and returns an array containing all the properties.


	const cheerio = require('cheerio');

	const $ = cheerio.load(html);
	const propertyList = [];
	
	console.log('Extract information from the HTML...');
	
	$(".dkr2t82").each((_, el) => {
	   const link = $(el).find('a._1lw0o5c2').attr('href');
	   const tagsElement = $(el).find('ul._1ial65f0 li');
	   const configsElement = $(el).find('ul._1wickv0 li');
	   const price = $(el).find('._1egbt4s3r p:last-child').text();
	   const title = $(el).find('h2.m6hnz61').text();
	   const address = $(el).find('address.m6hnz62').text();
	   const description = $(el).find("p.m6hnz63").text();
	
	   const tags = [];
	   const configs = {};
	
	   tagsElement.each((_, el) => {
		   tags.push($(el).text().replaceAll(' ', '_').toLowerCase())
	   })
	
	   configsElement.each((_, el) => {
		   const label = $(el).find('span._1wickv2').text().replaceAll(' ', '_').toLowerCase();
		   const count = $(el).find('span:last-child').text();
	
		   configs[label] = +count;
	   })
	
	   propertyList.push({
		   description,
		   price,
		   title,
		   address,
		   tags,
		   configuration: configs,
		   link: link.startsWith('https') ? link : `https://www.zoopla.co.uk${link}`
	   });
	});
	
	console.log('JSON result:', propertyList);

As you can see, we’re using the identified HTML tags and CSS selectors to navigate the DOM and pick specific elements.

Once our scraper gets all these details, we then push() the results into our empty list (propertyList) to get them organized, making it easier to export the information into a JSON file.

Here is the complete code of the index.js file:

<pre class="wp-block-syntaxhighlighter-code">
	const axios = require('axios');
	const cheerio = require('cheerio');
	
	const ZOOPLA_PAGE_URL = 'https://www.zoopla.co.uk/for-sale/property/liverpool/?q=Liverpool%2C+Merseyside&results_sort=newest_listings&search_source=home';
	const API_URL = 'https://api.scraperapi.com';
	const API_KEY = '<API_KEY>' // <--- Enter your API key here
	
	const webScraper = async () => {
	   console.log('Fetching data with ScraperAPI...');
	
	   const queryParams = new URLSearchParams({
		   api_key: API_KEY,
		   url: ZOOPLA_PAGE_URL,
		   country_code: 'uk'
	   });
	
	   try {
		   const response = await axios.get(`${API_URL}?${queryParams.toString()}`);
	
		   const html = response.data;
	
		   const $ = cheerio.load(html);
		   const propertyList = [];
	
		   console.log('Extract information from the HTML...');
	
		   $(".dkr2t82").each((_, el) => {
			   const link = $(el).find('a._1lw0o5c2').attr('href');
			   const tagsElement = $(el).find('ul._1ial65f0 li');
			   const configsElement = $(el).find('ul._1wickv0 li');
			   const price = $(el).find('._1egbt4s3r p:last-child').text();
			   const title = $(el).find('h2.m6hnz61').text();
			   const address = $(el).find('address.m6hnz62').text();
			   const description = $(el).find("p.m6hnz63").text();
	
			   const tags = [];
			   const configs = {};
	
			   tagsElement.each((_, el) => {
				   tags.push($(el).text().replaceAll(' ', '_').toLowerCase())
			   })
	
			   configsElement.each((_, el) => {
				   const label = $(el).find('span._1wickv2').text().replaceAll(' ', '_').toLowerCase();
				   const count = $(el).find('span:last-child').text();
	
				   configs[label] = +count;
			   })
	
			   propertyList.push({
				   description,
				   price,
				   title,
				   address,
				   tags,
				   configuration: configs,
				   link: link.startsWith('https') ? link : `https://www.zoopla.co.uk${link}`
			   });
		   });
	
		   console.log('JSON result:', propertyList);
	   } catch (error) {
		   console.log(error)
	   }
	};
	
	void webScraper();
</pre>

Run the code with the command node index.js, and appreciate the result.

Running Zoopla code with node index.js

Wrapping Up

Building a web scraper for Zoopla can be done in the following steps:

  • Use Axios to send a request to ScraperAPI with the Zoopla page to scrape, and download the HTML content.
  • Parse the HTML with Cheerio to extract the data based on DOM selectors.
  • Format and transform the data retrieved to suit your needs.

The result is a list of relevant information about the properties for sale displayed on the Zoopla website.

Here are a few ideas to go further with this Zoopla Web scraper:

  • Retrieve the information about properties to rent
  • Make the Web scraper dynamic by allowing you to type the city directly.
  • Store the data in a database (RDBMS, JSON files, CSV files, etc…) to build historical data and make business decisions.
  • Use the Async Scraper service to scrape up to 10,000 URLs asynchronously.

To learn more, check out ScraperAPI’s documentation for Node.js.

Frequently-Asked Questions

Zoopla provides data related to real estate, you can scrape data about properties for sale or to rent. For each property, you can get property history, amenities, features, property tax information, and neighborhood information.

You can also scrape data about real estate agents. For each agent, you can get professional contact and active listings.

By scraping Zoopla you can gather valuable information such as:

  • Insights into market trends, property values, neighborhood characteristics, and more
  • From the current prices, forecast the areas that will become attractive
  • From the data analyzed, apply strategies for better positioning within the real estate industry
  • Build an application on top of these data such as property comparators or investment tools.
  • Create visualizations or reports to share insights resulting from the analysis.

Zoopla employs measures to prevent scraping activities on their platform as intensive scraping can impact the performance of their website and degrade the user experience. Zoopla uses methods such as IP blocking, CAPTCHA challenges, rate limiting, or employing technology to identify and deter automated scraping bots.

About the author

Eric Cabrel Tiogo

Eric Cabrel Tiogo

Eric Cabrel Tiogo is a software developer and tech mentor specializing in Java, Node.js, Typescript, GraphQL, AWS, Docker, and React. He runs a popular backend-focused blog, a developer newsletter, and actively contributes to OSS Cameroon, an open-source community. He's known for his CI/CD expertise with GitHub Actions and GitLab CI. Connect with him on Twitter and explore his work at blog.tericcabrel.com.

Table of Contents

Related Articles

Talk to an expert and learn how to build a scalable scraping solution.