Homes.co.nz Scraper - Property Listings, Valuations & Agents avatar

Homes.co.nz Scraper - Property Listings, Valuations & Agents

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Homes.co.nz Scraper - Property Listings, Valuations & Agents

Homes.co.nz Scraper - Property Listings, Valuations & Agents

Scrape Homes.co.nz listings by location or URL with pagination. Extract property details, valuations, agents, branch information, media and open homes. Search multiple locations per run with filters for status, price, bedrooms and bathrooms.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

15

Total users

1

Monthly active users

5 days ago

Last modified

Share

Homes.co.nz Scraper: New Zealand Property Listings, Valuations & Agent Details

Homes.co.nz Scraper turns Homes.co.nz into a clean New Zealand property data feed. Search any location or paste Homes detail and map links to collect for sale, for rent, just sold and off market listings with prices, bedrooms and bathrooms, floor and land area, photos and open home times, plus (when enabled) council valuations, title details, and agent and agency contacts. Run it once, or schedule it and get back only what changed, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Two clean ways to find listings. Search by location name, or paste Homes detail and map links directly. Mix multiple locations or multiple URLs in one run.
  • Reads the site's own structured data, not page HTML. Detail and map pages are resolved from the page's embedded application state and the site's gateway API, so extraction stays stable when the page layout changes.
  • Dense areas are fully covered. Map searches recursively subdivide the viewport whenever Homes' own map endpoint caps a single call's results, so listings in busy cities are not silently dropped.
  • Bedroom and bathroom minimums are double checked. Each returned listing's own room counts are verified again after the fetch, since Homes' own map filter is not reliably narrowing at low minimums.
  • Optional deep enrichment. Turn on Fetch Property Cards to add council valuation, title, branch and agent details, or turn it off to cut cost when you only need the core listing fields.
  • Built for schedules. Incremental mode tags every listing NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against your own tracked search, and Resume continues one interrupted large pull without re-paying for listings already saved.
  • Unreadable inputs fail loudly. If a location, a map page or Homes' map API cannot be read, the run fails instead of quietly returning an empty dataset. Individual listings that cannot be fetched are logged and skipped.

Use Cases

  • Property portals and comparison sites: mirror Homes.co.nz for sale, for rent and recently sold listings for a region into your own search experience.
  • Valuation and investment research: pull capital value, estimated value and estimated rental ranges alongside each listing to screen for opportunities.
  • Market monitoring: track a suburb or city on a schedule with Incremental mode to see new listings, price and status changes, and delistings as they happen.
  • Lead generation for agents and buyers' advocates: collect agent and agency contact details attached to active listings in your target areas.
  • Market trend analysis: build a historical dataset of prices, floor areas and listing counts for a region over time.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
type"listing"
id / listingId"12345678"
propertyId"98765432"
url / listingDetailUrl"https://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2"
title / headline"25-26 Marion Street, Te Aro, Wellington"
description"Stylish two-level apartment close to the CBD..."
status / listingBucket / propertyStateCode1 / "for_sale" / 0 (status is the site's own numeric status code, passed through as-is and empty on sold and off-market rows. listingBucket says which bucket the row is in: for_sale = 0, just_sold = 1, off_market = 2, for_rent = 3 in propertyStateCode. Use it to tell the rows of an All homes run apart; empty when Fetch Property Cards is off and the listing has no property record)
price / displayPrice"Auction, 14 Oct 2026"
priceValue950000
currency"NZD"
bedrooms / bathrooms / carSpaces3 / 2 / 1
floorArea / landArea120 / 450 (square metres)
address / addressParts / regionName"25-26 Marion Street, Te Aro, Wellington" / { suburb, city } / "WELLINGTON" (the NZ region, looked up from the property record's region id; empty when Fetch Property Cards is off or the id is not one we have confirmed)
latitude / longitude-41.2946 / 174.7766
propertyType / listingType"House" / "residential"
agentNames / agencyName["Jane Smith"] / "Sample Realty"
openHomes / openHomeCountopen home time slots / 2
imageUrls / mediaCountarray of photo URLs / 18
solarEstimate / solarPotential / propertySalesCount"1,054" / "Excellent" / 8 (the site's solar panel estimate and rating, empty when the property has none, and its sales count)
valuations.capitalValue820000 (when Fetch Property Cards is on)
estimates.estimatedValue905000 (when Fetch Property Cards is on)
titleRecord.legalDescription"Lot 4 DP 12345" (when Fetch Property Cards is on)
publishedAt / updatedAtISO timestamps
changeType / changedFields"NEW" / [] (Incremental mode only)
fetchedAtISO timestamp this row was scraped

Every item is the same record shape whether it came from a location search, a map URL or a direct detail URL. Each row also carries branch, agents, propertyDetails, identifiers, sourceEndpoints and seedContext bookkeeping objects (fingerprint and internal ids, the API URLs that produced the row, and the search that seeded it), plus a videoUrls array when a listing includes a virtual tour, and a raw object with the full source payloads when Include Raw Structured Payloads is switched on. With Fetch Property Cards off, the fields that come from the property card are empty: valuations, estimates, titleRecord, propertyDetails, identifiers, agent, branch/branches, agencyName and the suburb, city and region inside addressParts. agentNames and agents can still fill from the listing detail.

How to Use

  1. Pick a Collection Mode: search (by one or more location names) or url (paste Homes detail or map links).
  2. Fill in the fields for that mode, then set the filters under Filters & sort (listing status, minimum bedrooms and bathrooms, price range, sort order). These filters apply to location searches and to map URLs; a single detail URL always returns that one listing.
  3. Set Max Listings (and optionally Max Pages / Listings Per Page) to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search a location for listings with at least 3 bedrooms:

{
"mode": "search",
"locations": ["Wellington"],
"listingStatus": "for_sale",
"minBedrooms": 3,
"maxListings": 50
}

Direct Homes links (one detail page, one map area):

{
"mode": "url",
"urls": [
"https://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2",
"https://homes.co.nz/map/wellington?lat=-41.2865&lng=174.7762&zoom=13"
],
"listingStatus": "for_sale"
}

Price-filtered rentals, newest first:

{
"mode": "search",
"locations": ["Auckland Central"],
"listingStatus": "for_rent",
"minPrice": 400,
"maxPrice": 800,
"sortBy": "published_desc",
"maxListings": 100
}

Recurring monitoring of a suburb, with expired listings flagged:

{
"mode": "search",
"locations": ["Wellington"],
"listingStatus": "for_sale",
"incrementalMode": true,
"emitExpired": true,
"maxListings": 0
}

The URLs field is pre-filled with one example of each shape, so URL mode with the field untouched scrapes those examples. Clear it and paste your own links.

Link shapeExampleBehaviour
Detail pagehttps://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2One property: an active listing, or a sold / off-market property built from its property record. A trailing slash or tracking query is fine.
Map page with coordinateshttps://homes.co.nz/map/wellington?lat=-41.2865&lng=174.7762&zoom=13Scans that viewport.
Map page, cityhttps://homes.co.nz/map/wellingtonScans the city area.
Map page, suburbhttps://homes.co.nz/map/wellington/te-aroScans the suburb area.
www. hosthttps://www.homes.co.nz/map/wellington?lat=...Treated as the bare host, query kept.
status parameter...&status=for_saleIgnored; the Listing Status input decides the bucket. A warning is logged.
Bare /map, short /address/<id>, other linkshttps://homes.co.nz/mapSkipped with a loud warning in the log. If no URL is usable the run fails. A skipped URL also prevents EXPIRED from being emitted in incremental mode.

Location searches match plain names such as Wellington; a name with no match fails the run with a clear error.

Filter notes. There is no "sold within N months" filter: the site's map endpoint has no server-side sold-date parameter (eight candidate parameter names returned the identical unfiltered sold set), so the just_sold bucket is returned as the site serves it. all_homes is served by the site itself (every status flag set together). Bedroom and bathroom ranges are verified client-side on each returned row.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/homes-co-nz-scraper").call(run_input={"mode": "search", "locations": ["Wellington"], "listingStatus": "for_sale"})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["address"], listing["price"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/homes-co-nz-scraper').call({ mode: 'search', locations: ['Wellington'], listingStatus: 'for_sale' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How Max Listings and Max Pages shape a run

Search and map-URL targets resolve their whole candidate set from Homes' map API in one pass, recursively subdividing the map viewport whenever a dense area is capped by the site's own endpoint, then slice that in-memory set into output pages purely for bookkeeping rather than real page by page requests. Leave Max Pages at 0 to walk every page, bounded only by Max Listings and the site's own candidate ceiling. Set Max Pages to a specific number only when you want an explicit page cap below that natural stop.

Resume and recurring updates

  • Resume from a prior run (resumeFromRunId) continues one interrupted crawl: paste its run or dataset ID and the actor skips every listing already saved there, so this run only appends new listings.
  • Incremental mode (incrementalMode) is for a search or URL list you run on a schedule. The actor remembers the previous run itself, keyed on a hash of your search scope, with no ID to paste, and classifies each listing NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED.
    • REAPPEARED only happens for a listing that a previous complete run already tombstoned as EXPIRED, and which then shows up again. It is not produced by default and needs that prior EXPIRED event first.
    • EXPIRED is only emitted when emitExpired is on and the run completed a full, uncapped pass of every location and URL in scope. A run capped by Max Listings or Max Pages, a map area too dense to fully resolve, or a run that also sets resumeFromRunId, never emits EXPIRED for that scope, so a listing that simply was not reached is never mistaken for one that was delisted.
  • stateKey overrides the auto-derived tracked-search identity, which is otherwise a hash of the mode, the locations or URLs, the listing status, bedroom, bathroom and price filters, and Fetch Property Cards (sort order and the output caps are not part of it). Combining incrementalMode with resumeFromRunId only works for the very first incremental run for a given state key; once a real baseline exists, the run fails fast instead of guessing.
  • ignoreFieldsForChanges lists fields to leave out of change detection. Everything else in the row is compared, except the actor's own crawl bookkeeping (fetchedAt, pageIndex, sourceEndpoints, seedContext), which is always ignored. Ignored fields are still returned. Changing the list never causes a one-time wave of UPDATED rows. A capped or partial run never emits EXPIRED.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title (the listing's headline or address) and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
  3. For Notion, also set notionParentPageUrl to the page where item pages should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (by location) or url (paste Homes links).
locationsarray["Wellington", "Auckland Central"]Location names to resolve and search. Used when mode is search. Leaving the field untouched in search mode scrapes Wellington and Auckland Central; clear it and add your own names to search elsewhere.
urlsarrayone example of each supported shape (a detail link, a map link with coordinates, a bare-city map link, a suburb map link)Homes detail or map URLs. Required when mode is url. Leaving the field untouched in URL mode scrapes those four examples.
listingStatusstringfor_salefor_sale, for_rent, just_sold, off_market, or all_homes (every one of those together, as the site's own map shows them). Applies to location searches and map URLs. Sold and off-market properties have no active listing, so their rows are built from the property record (address, price, rooms, areas, valuation and estimate data, agent and branch) and listingDetailApi is absent from their sourceEndpoints.
minBedroomsintegernone (no minimum)Only listings with at least this many bedrooms, verified against each returned listing.
minBathroomsintegernone (no minimum)Only listings with at least this many bathrooms, verified against each returned listing.
maxBedroomsintegernoneOnly listings with at most this many bedrooms, verified against each returned listing after the fetch (a tight range can return fewer rows than maxListings).
maxBathroomsintegernoneOnly listings with at most this many bathrooms, verified the same way.
minPriceintegernoneLower price bound (NZD) sent with the structured query.
maxPriceintegernoneUpper price bound (NZD) sent with the structured query.
sortBystringdefaultdefault, published_desc, published_asc, price_desc, or price_asc.
maxListingsinteger20Hard ceiling on listings output across the whole run (0 = no cap).
maxPagesinteger0Output pages to emit per target (0 = walk every page).
pageSizeinteger20Listings to emit on each output page.
fetchPropertyCardsbooleantrueInclude extra valuation, title, branch and agent data (one extra request per listing).
includeRawApiResponsesbooleanfalseInclude the raw structured API payloads in each item, for debugging.
resumeFromRunIdstringnoneContinue one interrupted run: paste its run or dataset ID.
incrementalModebooleanfalseTrack this search across scheduled runs and classify each listing's change type.
stateKeystringnone (auto-derived)Override the auto-derived tracked-search identity for Incremental mode.
emitUnchangedbooleanfalseAlso return (and bill) listings unchanged since the last incremental run.
emitExpiredbooleanfalseAlso return (and bill) listings that dropped out since the last incremental run, only after a complete scan.
ignoreFieldsForChangesstring[][]Incremental mode only: field names or dotted nested paths (for example propertyDetails.display_estimated_value_short) that never trigger UPDATED and never appear in changedFields. They are still returned in every row.
proxyConfigurationobject{ "useApifyProxy": true }Proxy configuration for Homes requests.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: the page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"type": "listing",
"id": "12345678",
"listingId": "12345678",
"propertyId": "98765432",
"url": "https://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2",
"canonicalUrl": "https://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2",
"title": "25-26 Marion Street, Te Aro, Wellington",
"description": "Stylish two-level apartment close to the CBD.",
"status": 1,
"price": "Auction, 14 Oct 2026",
"displayPrice": "Auction, 14 Oct 2026",
"priceValue": 950000,
"currency": "NZD",
"publishedAt": "2026-08-20T02:00:00.000Z",
"address": "25-26 Marion Street, Te Aro, Wellington",
"addressParts": { "full": "25-26 Marion Street, Te Aro, Wellington", "suburb": "Te Aro", "city": "Wellington", "region": "Wellington" },
"bedrooms": 3,
"bathrooms": 2,
"carSpaces": 1,
"floorArea": 120,
"landArea": 450,
"latitude": -41.2946,
"longitude": 174.7766,
"propertyType": "House",
"listingType": "residential",
"agentNames": ["Jane Smith"],
"agencyName": "Sample Realty",
"openHomes": [{ "date": "2026-10-05", "start_time": "13:00", "end_time": "13:30" }],
"imageUrls": ["https://images.homes.co.nz/sample1.jpg", "https://images.homes.co.nz/sample2.jpg"],
"mediaCount": 18,
"valuations": { "capitalValue": 820000, "improvementValue": 340000, "landValue": 480000, "revisionDate": "2024-09-01" },
"estimates": { "estimatedValue": 905000, "estimatedValueLow": 860000, "estimatedValueHigh": 950000, "grossYield": 3.8 },
"titleRecord": { "legalDescription": "Lot 4 DP 12345", "certificateOfTitle": "WN123/456", "ownershipType": "Freehold" },
"sourceEndpoints": { "pageUrl": "https://homes.co.nz/address/wellington/te-aro/25-26-marion-street/o02G2", "listingDetailApi": "https://gateway.homes.co.nz/listing/12345678/detail" },
"fetchedAt": "2026-09-28T04:00:00.000Z"
}

Plan Requirement

The default proxy setting (Apify datacenter proxy) is enough for Homes.co.nz: the site served listing, map and home pages without any challenge in our measurements, so no residential proxy is needed. Requests are retried automatically, and if the Apify proxy is unavailable to your account the run continues on a backup connection. A free Apify plan has no access to the Apify proxy: it is refused, the run continues on the backup connection, and pages are still served. The run only fails with the first message below if the backup connection is refused as well, in which case a paid Apify plan (or your own proxy URLs in the Proxy Configuration field) is needed.

If no page can be read, the run fails with one of these messages instead of returning an empty dataset:

  • The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid.
  • No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested homes.co.nz pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again.
  • Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later.
  • Could not load any of the N listing(s) found (every property request failed), so nothing was collected. This is a data-loading problem, not an empty search. Please try again later. (N is the number of listings the search found; this appears only when every one of them failed to load and nothing was pushed.)

When the residential tier is refused, the log also carries a warning that the selected connection is unavailable and the run is continuing on a backup connection, and a line notes when a page was served over the backup connection. That line is not logged when you chose to run without a proxy, because that connection is then the only one used.

FAQ

How much does it cost?

Billing has two events: an actor start event (once per run) and a result event, charged once for each row pushed to the dataset. Property card enrichment (Fetch Property Cards) is not a separate charge: it only adds one extra request per listing, which affects run time. In Incremental mode, UNCHANGED and EXPIRED rows are pushed and billed only when Emit UNCHANGED or Emit EXPIRED is on; suppressed rows are never charged. Listings that cannot be fetched are skipped and not charged. Sold and off-market properties are returned as ordinary rows built from the property record, and each pushed row is a result event like any other. The Pricing tab shows the current rates. Use Max Listings to cap the cost of any run.

Which dataset views are available?

The dataset has three views: Overview (id, title, price, address, bedrooms, bathrooms, car spaces, property type, agency, url), Detail (address, valuations, estimates, solar estimate and potential, sales count, title record, property details, open homes, url) and Changes (address, change type, changed fields, first and last seen, url; useful in Incremental mode).

This actor collects only publicly available property listing data. You are responsible for how you use it: follow Homes.co.nz's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Valuation estimates, photos and agent details may be subject to third-party rights.

Can I get only new, changed or removed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then tags every listing NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against your last run for that same search or URL list, and unchanged listings are not returned or billed unless you turn on Emit UNCHANGED.

What is the difference between "Resume from a prior run" and Incremental mode?

They solve different problems. Resume from a prior run continues one interrupted large pull: paste the earlier run or dataset ID and this run skips every listing already saved there. Incremental mode is for a search or URL list you run on a schedule: it remembers the previous run itself, with no ID to paste, and classifies each listing against that stored state. Combining the two only works for the very first incremental run for a given tracked search.

Why did my run fail instead of returning an empty dataset?

The run fails when it cannot read what was asked for: the input is invalid (for example Search mode with no locations), Homes' address search cannot resolve a location, a detail or map URL's page cannot be loaded or read, Homes' map API keeps failing after retries, or a Resume from a prior run ID does not match a run or dataset this Apify account can read (or is combined with Incremental mode after a baseline already exists). Once a listing has been found, a failure fetching its detail or property card after retries does not fail the run: that one listing is skipped and logged, and the run finishes with whatever it could read.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more Homes data?

Pair this actor with these related scrapers from the same team:

🧩 Homes.com Scraper
Scrape US property records from Homes.com. Pick a city, state or ZIP and a channel (for...
🏠 RealestateCo NZ
Search and extract all real estate properties for sale, rent, and sold across New Zealand...
🚗 Trade Me NZ Scraper
Scrape trademe.co.nz across all five sections: Marketplace goods and auctions, Property...
🏠 Trulia Scraper
Scrape Trulia.com property listings by location, filters, or URL. Extract prices, beds...
🏠 OnTheMarket Scraper
Scrape onthemarket.com for-sale, to-rent and new-homes listings with 85+ fields: price...
🧩 Mortgagee Sale Scraper
Scrape mortgagee-sale and distressed property leads across Australia and New Zealand...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.