# MyHome.ie Scraper - Ireland Real Estate Data & Prices (`neverempty/myhome-listings`) Actor

MyHome.ie listings for sale or rent as clean JSON: price as a number with its meaning (sale, monthly rent, auction AMV, POA), bedrooms, bathrooms, floor area, BER rating, address with coordinates, the agency, listing dates and viewings. No agent contacts, no private landlords named. Unofficial.

- **URL**: https://apify.com/neverempty/myhome-listings.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.73 / 1,000 listing returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## MyHome.ie Scraper - Ireland Homes for Sale & Rent

Pull property listings from **MyHome.ie** — one of Ireland's two big property portals — as clean JSON: the price as a number with its meaning, bedrooms, bathrooms, floor area, BER rating, address with coordinates, the agency, listing dates, open viewings and the main image, for sale or to rent, for any county, postal district or town MyHome covers.

*Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by MyHome.ie. All product names are trademarks of their respective owners.*

No API key. Reads the same public pages a visitor sees.

***

### Run it tomorrow and you only get what is new

Schedule this Actor with `monitoringMode: true` and each run returns **only the listings it has not returned before**. Not "here is everything again, please de-duplicate it yourself" — the Actor remembers what it already gave you, so a daily feed of a 4,000-listing search costs you the handful of new homes, not 4,000 rows every morning. **You are never charged for the same property twice.**

Listings your filters removed are remembered too, so widening a filter later does not resurrect them as false "new" listings. Listings that did not fit under your limit are **not** remembered, so they are still waiting on the next run instead of being silently lost.

***

### Why this one is different

#### The price means what it says

`price` is a number in euro; `priceType` says whether it is a **sale** price, a **monthly-rent** or **weekly-rent** (the unit is read from MyHome's own text, "€2,500 / month", never assumed), and `priceQualifier` flags an **AMV** (an auction's advised minimum value — 2 of the 60 listings measured), a "from" or "guide" price, or **POA**. A price on application stays `null` with its text — it is never turned into a zero. Medians in the 60 listings measured: **€585,000** for sale in Dublin, **€2,500** a month to rent.

#### Coordinates from the brochure map, not the decorative field

MyHome's list data carries two coordinate fields. One (`Location`) was 0,0 on 71 of the 80 listings inspected; the other (`BrochureMap`) is the real position. This Actor returns `latitude` / `longitude` from the real one, and `null` when MyHome has none — never a point in the Gulf of Guinea. `isMappedAccurately` is MyHome's own flag.

#### No agent contact, no private landlord named

Every listing in MyHome's list data carries the agency's e-mail, and 51 of the 80 inspected carried the negotiator's name (44 an e-mail, 35 a photo). This Actor returns the **agency name and logo only**. A private landlord's listing (16 of the 20 Dublin rentals measured) comes back as `advertiserType: "private"` with no name at all. Phone numbers written into an address are removed.

#### Dates, the way MyHome stamps them

`createdAt`, `activatedAt` and `refreshedAt` are MyHome's own timestamps (created, activated, last refreshed), converted from Irish time to UTC. `activatedWithinDays` filters on the activation date — the closest thing MyHome publishes to "listed on".

#### The area is whatever MyHome accepts

MyHome's listing URLs are `/residential/<area>/property-for-sale` and `/rentals/<area>/property-to-rent`, where the area is a county (`cork`), a postal district (`dublin-4`) or a town (`swords`). Not every town has its own page: an area MyHome does not know answers 404, which comes back as a free `no-such-search` row rather than an empty result. `searchedLocation` carries the area as MyHome names it ("Co. Cork").

#### Filters run here

Every filter — price, bedrooms, bathrooms, area, property type, BER, sale agreed, build-to-rent, auctions, advertiser, activation date, keywords, agency — runs on the rows already fetched. Only the area and the page number are sent to MyHome (its `robots.txt` allows exactly that and nothing else in the query string). Nothing extra is requested and nothing extra is charged. A listing is never dropped for a value MyHome did not publish.

***

### Input

Either paste a MyHome listing page URL, or build one from the fields below.

| Field | Type | Default | Description |
|---|---|---|---|
| `searchUrl` | string | — | e.g. `https://www.myhome.ie/residential/dublin/property-for-sale`. Only the path is kept |
| `channel` | string | `sale` | `sale` (/residential) or `rent` (/rentals) |
| `location` | string | `dublin` | A county, postal district or town as MyHome spells it: `dublin`, `cork`, `galway`, `limerick`, `dublin-4`, `swords` … (each of these answered 200 on 2026-09-05; a town without its own page answers 404) |
| `maxListings` | integer | 20 | 1-1000. One listing = one row = one charged event. 20 listings per page |
| `maxPages` | integer | 0 | Hard cap on requests; 0 = decide from `maxListings`. Reading pages is free |
| `useProxy` | boolean | `false` | Off by default — MyHome answers Apify's network directly. Switches on by itself if blocked |
| `keywords` / `keywordMatch` / `excludeKeywords` | array / string / array | — | Match on address, type, agency, price text and BER |
| `agencyNames` | array | — | Keep only these agencies (partial match). Private landlords carry no agency name, so they are dropped by this filter |
| `minPrice` / `maxPrice` | integer | 0 | EUR. Sale price or monthly rent. **A POA listing is kept**; a weekly rent or a rent without a unit is kept |
| `requirePrice` | boolean | `false` | Drop POA listings |
| `minBedrooms` / `maxBedrooms` | integer | -1 | -1 = off. **An unpublished count is kept** |
| `minBathrooms` | integer | 0 | |
| `minSizeSqm` / `maxSizeSqm` | integer | 0 | m² |
| `propertyTypes` | array | — | Partial match on MyHome's words: `Apartment`, `Terraced House`, `Semi-Detached House`, `Detached House`, `Duplex`, `Penthouse`, `Site` … (`detached` also matches `Semi-Detached`) |
| `berRatings` | array | — | `A1` … `G`, `EXEMPT`. MyHome also publishes bare letters (`A`, `B`, `C` … 24 of the 80 listings inspected) and `A0`; list them too if you want them |
| `excludeSaleAgreed` | boolean | `false` | Drop sale-agreed listings |
| `excludeBuildToRent` | boolean | `false` | Drop build-to-rent developments |
| `excludeAuctions` | boolean | `false` | Drop AMV (auction) listings |
| `advertiserType` | string | `any` | `agency` or `private` |
| `activatedWithinDays` | integer | 0 | By MyHome's activation date. 0 = off |
| `monitoringMode` | boolean | `false` | Return only listings not returned on a previous run |
| `resetMonitoringState` | boolean | `false` | One-shot: forget what was already returned |

```json
{ "channel": "sale", "location": "dublin-4", "maxListings": 100,
  "minBedrooms": 2, "maxPrice": 800000, "berRatings": ["A1", "A2", "A3", "B1", "B2", "B3"], "excludeAuctions": true }
```

#### Monitoring mode turns this into a daily feed

MyHome's default order puts paid placements first, not the newest listings. In monitoring mode this Actor returns **only the listings it has not returned before**, reading on past the ones it already knows — up to 60 pages, or `maxPages` — until it has `maxListings` new ones. Listings removed by your filters are remembered too, so changing a filter later does not resurrect them as false "new" listings — and listings that simply **did not fit under `maxListings`, or were cut off by the run's charge limit, are not remembered**, so they are still waiting for you on the next run rather than being silently lost. Combine it with `activatedWithinDays` to keep only genuinely recent stock.

Measured on 2026-09-05: **4,225** homes for sale in Dublin (212 pages); **526** to rent in Dublin; **1,652** for sale in Co. Cork.

***

### Output

One row per listing:

```json
{
  "source": "myhome.ie",
  "status": "ok",
  "listingId": "5019243",
  "title": "30 FLEMING ROAD, Drumcondra, Dublin 9",
  "url": "https://www.myhome.ie/residential/brochure/30-fleming-road-drumcondra-dublin-9/5019243",
  "searchedLocation": "Dublin",
  "transactionType": "sale",
  "propertyType": "Terraced House",
  "propertyStatus": "ForSale",
  "isSaleAgreed": false,
  "isNew": false,
  "isBuildToRent": false,
  "price": 395000,
  "priceCurrency": "EUR",
  "priceType": "sale",
  "priceQualifier": null,
  "priceText": "€395,000",
  "rentalTerm": null,
  "bedrooms": 2,
  "bathrooms": 1,
  "sizeSqm": 70,
  "berRating": "F",
  "address": "30 FLEMING ROAD",
  "displayAddress": "30 FLEMING ROAD, Drumcondra, Dublin 9",
  "latitude": 53.37224578857422,
  "longitude": -6.2599687576293945,
  "isMappedAccurately": true,
  "advertiserType": "agency",
  "agencyName": "MOVEHOME ESTATE AGENTS",
  "agencyLogoUrl": "https://photos-a.propertyimages.ie/groups/2/8/3/7382/logo.jpg",
  "listingTier": "premium",
  "relatedListingsCount": 0,
  "openViewings": [],
  "photoCount": 15,
  "mainImageUrl": "https://photos-a.propertyimages.ie/media/3/4/2/5019243/885e6523-5989-4dd4-9cbe-d3b8c0a66679_l.jpg",
  "createdAt": "2026-08-06T11:18:31.580Z",
  "activatedAt": "2026-08-28T08:09:39.773Z",
  "refreshedAt": "2026-09-05T09:48:44.293Z",
  "scrapedAt": "2026-09-05T10:44:20.523Z"
}
```

Measured across 60 live listings on 2026-09-05 — 40 for sale and 20 to rent in Dublin: id, address, URL, type, status, advertiser, tier, image and created / refreshed dates on **60 of 60**; a price on **59**; bedrooms on **58**; bathrooms on **54**; floor area on **44**; a BER on **55**; coordinates on **51**; an agency name on **44** (the other 16 are private landlords); an activation date on **44**; open viewings on **6**. `relatedListingsCount` is the number of sister units MyHome groups with a development listing.

#### Rows that are never charged

| `status` | when |
|---|---|
| `no-results` | MyHome reports zero listings for this search. That is its answer, not a failure |
| `no-such-search` | MyHome answered HTTP 404 — what it does for an area it does not know. **Not** a claim that there is nothing there |
| `no-filter-match` | Listings were read, but your filters removed all of them. The row says how many were read |
| `no-new-listings` | Monitoring mode: nothing new since the previous run |
| `unreadable` | The page could not be read, its data was missing, or it claimed a total above zero while yielding nothing |

***

### Pricing

Pay per listing returned. Rows that report an empty search, an unknown area, a filter that matched nothing, or a page that could not be read are **not** charged.

***

### Notes

- `robots.txt` was read in full on 2026-09-05. It explicitly allows `?page=N` on the listing sections and disallows every other query string, the account pages and the feed. This Actor requests only `/residential/<area>/property-for-sale` or `/rentals/<area>/property-to-rent` with `?page=N`.
- Only public pages are read. No login, no API key. The API key MyHome embeds in its own pages is not used and not returned.

# Actor input Schema

## `searchUrl` (type: `string`):

Paste a MyHome listing page, e.g. https://www.myhome.ie/residential/dublin/property-for-sale or https://www.myhome.ie/rentals/cork/property-to-rent. Only the path is used; query parameters are dropped because MyHome's robots.txt allows only ?page= and every filter runs on the rows already fetched. When set, channel and location are ignored.

## `channel` (type: `string`):

sale = /residential/.../property-for-sale, rent = /rentals/.../property-to-rent. A rental's unit (monthly, weekly) is read from the price text and returned as rentalTerm.

## `location` (type: `string`):

An area as MyHome spells it in its own addresses: a county (dublin, cork, galway, limerick, waterford), a postal district (dublin-4) or a town (swords). Not every town has its own page: an area MyHome does not know answers 404 and is reported as a no-such-search row.

## `maxListings` (type: `integer`):

How many listings to return. You are charged for the rows you actually receive. MyHome serves 20 listings per page (Dublin for sale: 4,225 listings on 212 pages on 2026-09-05).

## `maxPages` (type: `integer`):

Hard cap on the number of list pages requested. 0 = decide from maxListings (20 listings per page, plus a margin). Reading pages is free; only returned listings are charged.

## `useProxy` (type: `boolean`):

Off by default: MyHome answers Apify's network directly. If a request is blocked (403/429/503) the Actor switches to a proxy session by itself and retries.

## `keywords` (type: `array`):

Keep only listings whose address, type, agency, price text or BER rating contains these words. Matching is case-insensitive.

## `keywordMatch` (type: `string`):

any = at least one keyword must appear; all = every keyword must appear.

## `excludeKeywords` (type: `array`):

Drop listings containing any of these words.

## `agencyNames` (type: `array`):

Keep only listings from these agencies (partial match). Private landlords carry no agency name, so this filter drops them.

## `minPrice` (type: `integer`):

Sale price, or monthly rent. 0 = off. A listing whose price is on application is kept; a weekly rent or a rent without a unit is kept (not comparable with a monthly budget).

## `maxPrice` (type: `integer`):

Sale price, or monthly rent. 0 = off. A listing whose price is on application is kept.

## `requirePrice` (type: `boolean`):

Drop listings whose price is on application.

## `minBedrooms` (type: `integer`):

-1 = off. A listing with no bedroom count (site, studio) is kept.

## `maxBedrooms` (type: `integer`):

-1 = off.

## `minBathrooms` (type: `integer`):

0 = off.

## `minSizeSqm` (type: `integer`):

0 = off. A listing with no published area is kept.

## `maxSizeSqm` (type: `integer`):

0 = off.

## `propertyTypes` (type: `array`):

Partial match on MyHome's words: Apartment, Terraced House, Semi-Detached House, Detached House, End of Terrace House, Duplex, Penthouse, Bungalow, Cottage, Site. A listing with no type is kept.

## `berRatings` (type: `array`):

Keep only these Building Energy Ratings (A1, A2, B1 ... G, EXEMPT). MyHome also publishes bare letters (A, B, C ...) and A0 - list them too if you want them. A listing with no rating is kept.

## `excludeSaleAgreed` (type: `boolean`):

Drop listings flagged as sale agreed.

## `excludeBuildToRent` (type: `boolean`):

Drop listings flagged as build-to-rent.

## `excludeAuctions` (type: `boolean`):

Drop listings priced as an auction AMV (advised minimum value).

## `advertiserType` (type: `string`):

agency = estate agents only; private = private landlords only (rentals). any = both.

## `activatedWithinDays` (type: `integer`):

Keep only listings MyHome activated within this many days (its ActivatedOn date). 0 = off. A listing with no activation date is kept.

## `monitoringMode` (type: `boolean`):

Turn this on and schedule the Actor: each run returns only the listings it has never returned before, reading on past the ones it already knows (up to 60 pages, or maxPages) until it has maxListings new ones. Listings removed by your filters are remembered too. Listings that did not fit under the limit are not remembered, so they are still waiting for you on the next run.

## `resetMonitoringState` (type: `boolean`):

One-shot: forget every listing returned so far for this search. The next monitoring run returns everything again.

## Actor input object example

```json
{
  "channel": "sale",
  "location": "dublin",
  "maxListings": 20,
  "maxPages": 0,
  "useProxy": false,
  "keywords": [],
  "keywordMatch": "any",
  "excludeKeywords": [],
  "agencyNames": [],
  "minPrice": 0,
  "maxPrice": 0,
  "requirePrice": false,
  "minBedrooms": -1,
  "maxBedrooms": -1,
  "minBathrooms": 0,
  "minSizeSqm": 0,
  "maxSizeSqm": 0,
  "propertyTypes": [],
  "berRatings": [],
  "excludeSaleAgreed": false,
  "excludeBuildToRent": false,
  "excludeAuctions": false,
  "advertiserType": "any",
  "activatedWithinDays": 0,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per listing: address, the price as a number with its currency and what it means (sale, monthly or weekly rent, an auction AMV, or price on application), the price text as MyHome shows it, bedrooms, bathrooms, floor area, BER rating, coordinates from MyHome's brochure map, property type and status, sale-agreed / new / build-to-rent flags, the listing tier (premium, top spot, brand booster, standard), the agency name and logo (never the agent's name, e-mail or photo; private landlords are not named), open viewing times, photo count and main image, and the dates MyHome created, activated and last refreshed the listing. Every row names the area MyHome resolved the search to. Searches with no results, unknown areas (404), filters that matched nothing, and pages that could not be read come back as their own rows and are not charged.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchUrl": "",
    "keywords": [],
    "excludeKeywords": [],
    "agencyNames": [],
    "propertyTypes": [],
    "berRatings": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/myhome-listings").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchUrl": "",
    "keywords": [],
    "excludeKeywords": [],
    "agencyNames": [],
    "propertyTypes": [],
    "berRatings": [],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/myhome-listings").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchUrl": "",
  "keywords": [],
  "excludeKeywords": [],
  "agencyNames": [],
  "propertyTypes": [],
  "berRatings": []
}' |
apify call neverempty/myhome-listings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/myhome-listings"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TyZEhdg55xmJz1FRw/builds/uRqCGqbcjPmhYi2My/openapi.json
