All articles

Web Scraping Zoopla Real Estate Data using Python

Published Date May 15, 2025
Read 7 min
Web Scraping Zoopla Real Estate Data using Python

TL;DR

  • Use Scrapingdog’s API (1k free credits) to fetch Zoopla listing pages.

  • Parse with Python (requests + BeautifulSoup) to extract price, address, description.

  • Paginate by increasing the page number; collect rows and export to zoopla.csv with pandas.

  • Or skip parsing: send ai_query + ai_extract_rules to get structured JSON directly.

Zoopla is one of the UK’s leading property portals, packed with real estate listings, rental data, and housing market insights. Whether you’re a developer building a property comparison tool or a researcher tracking market trends, accessing this data programmatically can be incredibly useful.

In this guide, we’ll show you how to scrape property listings from Zoopla using Python, covering everything from navigating pagination to extracting key details like price, location, and property type, all while being mindful of best scraping practices. If you’re just starting out with web scraping, I highly recommend reading Web Scraping with Python. It’s a great resource for building a strong foundation.

Requirements To Scrape Data From Zoopla

I assume that you have already installed Python on your machine. If not, you can download it from here. Now, create a folder by any name you like. I am naming the folder as zoopla.

1mkdir tut

Install these 3 libraries inside this folder.

  • requests for making an HTTP connection with the target website.

  • BeautifulSoup for parsing the raw data.

  • Pandas for storing data in a CSV file.

Final step before moving to the coding part would be to sign up for a web scraping API. In this tutorial, we are going to use Scrapingdog.

0 tCk5Srh4js9TSUzE

Now, we should create a Python file where we can write the scraping code. I am naming the file as zoopla.py.

Let's Start Scraping Zoopla with Python

Before we start coding the scraper, take a moment to read Scrapingdog’s documentation; it’ll give you a clear idea of how we can use the API to scrape Zoopla at scale.

Once you have read the documentation, it is better to decide what information you want to extract from Zoopla in advance.

1 eoJFz7XChcFPd6CZmDtFQA

We are going to scrape the price, address, and description of the property. Let’s find the location of each data point in the DOM.

1 L9Fuvd TotMjcVksoYTQMQ

The pricing is stored inside the p tag with the class _64if862.

1 ooLuhtnQjI rDPh6SeUt7Q

The description is stored inside the p tag with the class m6hnz63.

1 yPSHiLGpwBEH7fme1VxG7A

The address is located inside the address tag itself.

1 gr11DN 6GUIFzDrm05mmdQ

Each property is located inside a div tag with the class dkr2t86.

Let’s code now.

Downloading raw HTML

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4
5l=[]
6obj={}
7
8params={
9 'api_key': 'your-api-key',
10 'url': 'https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home&pn=2',
11 'dynamic': 'false',
12 }
13
14response = requests.get("https://api.scrapingdog.com/scrape", params=params)
15
16print(response.status_code)

This is the basic Python code where we are making a GET request to the Scrapingdog API. Remember to use your own API key in the above code. Once you run the code, you should see 200 status code indicating a successful scrape.

1 RPB67aQtvZ8SJeNmyzGeMg

Parsing the data with BeautifulSoup

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4
5l=[]
6obj={}
7
8params={
9 'api_key': 'your-api-key',
10 'url': 'https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home&pn=2',
11 'dynamic': 'false',
12 }
13
14response = requests.get("https://api.scrapingdog.com/scrape", params=params)
15
16soup = BeautifulSoup(response.text, 'html.parser')
17
18allData = soup.find_all("div",{"class":"dkr2t86"})
19
20for data in allData:
21 try:
22 obj["price"]=data.find("p",{"class":"_64if862"}).text
23 except:
24 obj["price"]=None
25
26 try:
27 obj["address"]=data.find("address",{"class":"m6hnz62"}).text
28 except:
29 obj["address"]=None
30
31 try:
32 obj["description"]=data.find("p",{"class":"m6hnz63"}).text
33 except:
34 obj["description"]=None
35
36
37 l.append(obj)
38 obj={}
39
40print(l)

The code is pretty simple, but let me explain to you the logic behind it.

  • Finds all <div> elements with class "dkr2t86" and stores them in allData.

  • Loops through each element in allData.

  • Tries to extract the price from a <p> tag with class "_64if862". Sets to None if not found.

  • Tries to extract the address from an <address> tag with class "m6hnz62". Sets to None if not found.

  • Tries to extract the description from a <p> tag with class "m6hnz63". Sets to None if not found.

  • Stores all extracted data in a dictionary called obj.

  • Appends obj to the list l.

  • Resets obj to an empty dictionary for the next loop.

  • Prints the final list l containing all extracted records.

Once you run this code, you should see a beautiful JSON response like this.

1 3np30KNhOqjgRl6jxeKu8g

Handling Pagination

When you click on the II page from the bottom of the page, the URL of the page becomes https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home&pn=2. As you can see, a page parameter by the name pn appears within the URL, which can be used for changing the page number.

We have to run a for loop that can automatically change the page number within the URL and make a separate API call on every iteration.

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4
5l=[]
6obj={}
7
8for i in range(1,11):
9 params={
10 'api_key': 'your-api-key',
11 'url': 'https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home&pn={}'.format(i),
12 'dynamic': 'false',
13 }
14
15 response = requests.get("https://api.scrapingdog.com/scrape", params=params)
16
17 soup = BeautifulSoup(response.text, 'html.parser')
18
19 allData = soup.find_all("div",{"class":"dkr2t86"})
20
21 for data in allData:
22 try:
23 obj["price"]=data.find("p",{"class":"_64if862"}).text
24 except:
25 obj["price"]=None
26
27 try:
28 obj["address"]=data.find("address",{"class":"m6hnz62"}).text
29 except:
30 obj["address"]=None
31
32 try:
33 obj["description"]=data.find("p",{"class":"m6hnz63"}).text
34 except:
35 obj["description"]=None
36
37
38 l.append(obj)
39 obj={}
40
41
42print(l)

Saving data to CSV

Using the pandas library, we can save this data to a CSV file. Let’s see how it can be done.

df = pd.DataFrame(l) df.to_csv('zoopla.csv', index=False, encoding='utf-8')

  • Creates a DataFrame df from the list l.

  • Saves the DataFrame to a CSV file named zoopla.csv.

  • Disables the index column in the CSV using index=False.

Once you run it, you will find a CSV file by the name zoopla.csv.

1 VFQEhoBX3hytF3dfiGgqiA

Complete Code

You can, of course, scrape other details as well, but as of now, the code will look like this.

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4
5l=[]
6obj={}
7
8params={
9 'api_key': 'your-api-key',
10 'url': 'https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home',
11 'dynamic': 'false',
12 }
13
14response = requests.get("https://api.scrapingdog.com/scrape", params=params)
15
16soup = BeautifulSoup(response.text, 'html.parser')
17
18allData = soup.find_all("div",{"class":"dkr2t86"})
19
20for data in allData:
21 try:
22 obj["price"]=data.find("p",{"class":"_64if862"}).text
23 except:
24 obj["price"]=None
25
26 try:
27 obj["address"]=data.find("address",{"class":"m6hnz62"}).text
28 except:
29 obj["address"]=None
30
31 try:
32 obj["description"]=data.find("p",{"class":"m6hnz63"}).text
33 except:
34 obj["description"]=None
35
36
37 l.append(obj)
38 obj={}
39
40
41
42df = pd.DataFrame(l)
43df.to_csv('zoopla.csv', index=False, encoding='utf-8')

Get Structured Data without Parsing using Scrapingdog AI Scraper

If you want structured data without writing parsing logic or using BeautifulSoup, you can use AI parsing instead. Just submit a simple query, and the data gets parsed for you, no custom code required. You can read more about this parameter over here.

1import requests
2
3response = requests.get("https://api.scrapingdog.com/scrape", params={
4 'api_key': 'your-api-key',
5 'url': 'https://www.zoopla.co.uk/for-sale/property/london/?q=london&search_source=home&pn=1',
6 'dynamic': 'false',
7 'ai_query': 'Give me the price of each property in json format'
8 'ai_extract_rules': '{"price":"$xyz"}'
9 })
10
11print(response.text)

This will generate a JSON response that looks like this.

1{"price":"£425,000"},{"price":"£800,000"},{"price":"£575,000"},{"price":"£650,000"},{"price":"£1,100,000"},{"price":"£3,600,000"},{"price":"£450,000"},{"price":"£625,000"},{"price":"£1,350,000"},{"price":"£475,000"},{"price":"£950,000"},{"price":"£360,000"},{"price":"£685,000"},{"price":"£435,000"},{"price":"£1,695,000"},{"price":"£320,000"},{"price":"£450,000"},{"price":"£6

Advantages of this approach

  • No code required — Easily extract structured data without writing any parsing logic.

  • Faster implementation — Skip HTML structure analysis and get results instantly.

  • Handles messy HTML — AI can intelligently extract data even from inconsistent or nested layouts.

  • Reduces maintenance — No need to update scrapers when websites change minor HTML tags or classes.

  • Ideal for non-devs — Makes web scraping accessible to users without programming experience.

  • Cleaner output — Directly get structured JSON or CSV-ready data.

Key takeaways:

  • Zoopla listings can be scraped to extract structured data like property prices, locations, descriptions, and key features for analysis.

  • A Python setup using requests and parsing libraries allows you to collect and organize real-estate data efficiently.

  • Search pages and pagination need to be handled properly to gather data across multiple result pages.

  • Zoopla has anti-scraping protections, so headers, rate control, and smart request handling are important.

  • Structured property data can be used for market research, price tracking, and real-estate intelligence.

Conclusion

Scraping property listings from Zoopla with Python and Scrapingdog opens up a world of possibilities for real estate analysis, price tracking, and market research. With libraries like requestsBeautifulSoup, or even automation tools like PuppeteerYou can extract valuable data at scale. Whether you're building a real estate dashboard or feeding data into an ML model, Python makes the process efficient and flexible.

Additional Resources

Try Scrapingdog for Free!

Get 200 free credits to spin the API. No credit card required!