# SeLoger Scraper 💰 $0.9/1K France Real Estate + Agencies (`memo23/seloger-scraper`) Actor

À partir de $0.9/1K 💰 Scraper SeLoger : extraction par URL de recherche, d'annonce ou d'agence. Prix, m², pièces, chambres, DPE, charges, honoraires, meublé, balcon, garage, photos, GPS, téléphone et e-mail de l'agence. 99 champs. JSON, CSV ou Excel.

- **URL**: https://apify.com/memo23/seloger-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Real estate, Automation, Agents
- **Features:** Limited permissions
- **Stats:** 121 total users, 25 monthly users, 98.8% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.90 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SeLoger.com All-in-One Scraper — Search, Properties & Agencies

<details>
<summary><strong>Version française</strong></summary>

Extrait des annonces immobilières de SeLoger.com à partir d'une URL de recherche, d'annonce ou d'agence. Sans navigateur et sans connexion : vous collez l'URL et vous recevez des lignes structurées.

**Comment l'utiliser**

Ouvrez SeLoger, appliquez vos filtres (ville, prix, pièces, surface), copiez l'URL depuis la barre d'adresse et collez-la dans `startUrls`. L'actor reconnaît seul les trois types d'URL.

**Ce que vous obtenez**

Jusqu'à 99 champs par annonce : prix et prix au m², surface, pièces, chambres, DPE et émissions CO2, charges, honoraires, meublé, balcon, garage, photos, coordonnées GPS, plus le téléphone et l'e-mail de l'agence lorsqu'ils sont publiés.

**Offre gratuite**

Avec un compte Apify gratuit, vous obtenez jusqu'à 100 résultats par exécution, sans rien payer. Les offres payantes lèvent la limite : [tarifs Apify](https://apify.com/pricing).

Une question ou un champ manquant : ouvrez une issue sur la page de l'actor.

</details>

#### How it works

## ![How SeLoger Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-seloger.png)

All-in-one SeLoger.com scraper: **75+ data points per property row**, taken from the data shown on each listing page. Paste any mix of the **4 URL kinds** below and the actor auto-classifies each one:

| Input | Row(s) emitted |
|---|---|
| **Search page URL** as SeLoger's address bar shows it — `/recherche/{transaction}/{type}/…/{place-id}` (e.g. `/recherche/achat/appartement/ile-de-france/paris-75000/ad08fr31096`) — or the older `/immobilier/{transaction}/immo-{city-dept}/[bien-{type}/]` that redirects there (e.g. `/immobilier/achat/immo-paris-75/`; rentals are `/immobilier/locations/immo-paris-75/`, plural — the singular `/immobilier/location/` is a 404 on SeLoger and the actor rewrites it) | **N property rows** — one per property card. SeLoger shows only page 1 of these (12-14 cards; later page numbers repeat it), so the actor reads the search the page embeds and continues on the equivalent `/classified-search`, newest first. |
| **Filter search URL** — `/classified-search?classifiedBusiness=…&distributionTypes=…&locations=…&priceMin=…&priceMax=…` (the new SeLoger search shape with full filter support) | **N property rows**, same fields as the SEO shape. Paginates via `?page=N`. |
| **Property detail URL** — `/annonce/{transaction}/{region}/{dept}/{city}/{id}` or `/annonces/{type}/{slug}/{city-dept}[/{neighborhood}]/{id}.htm` | 1 property row: price, fees, mortgage, m², rooms, bedrooms, floor, address, neighborhood, postal code, DPE/GES energy ratings, construction year, lat/lng, agency name + profile URL, features, image URLs. |
| **Agency profile URL** — `/professionnels-immobilier/{opaque-id}` | 1 agency row + N property rows for every property the agency has listed. |

Pagination is handled automatically — `/classified-search` URLs page with `page`, and SEO listings continue on their `/classified-search` equivalent after page 1. The older `/list.htm?projects=…` query-style URL no longer works on SeLoger and is skipped up-front; use `/classified-search?...` instead (it's the modern replacement and works). JSON + CSV out.

> No SeLoger account, login or API key needed.

#### Why 75+ fields per row?

A SeLoger listing page holds far more than the price and the photos: the full property record, the energy diagnostic, nearby transport and the agency behind the ad. The actor returns all of it, so each row carries:

- **Property core** — propertyId, externalRef, title, propertyType, transactionType, rooms, bedrooms, livingArea (m²), plotSurface (m²), floor, neighborhood/district, city, postalCode, country, region
- **Pricing** — price (€), priceFormatted, pricePerM2, notaryFees, totalProjectCost, monthlyMortgage
- **Energy** — dpeRating (A–G), gesRating, dpeIndex (0–6), primaryEnergyKwh, finalEnergyKwh, co2EmissionsKgPerM2, annualEnergyCost (€ band), energyDiagnosticDate, energySources, constructionYear, buildingState
- **Geo** — latitude, longitude, isAddressPublished, geoIdHierarchy (7-level SeLoger location IDs)
- **Transport** — metro, bus, tramway, RER lines (with line numbers and brand colors) within walking distance
- **Co-ownership** — coOwnershipLots, coOwnershipChargesPerYear, coOwnershipProceedings
- **Media** — `imageUrls` (full carousel, up to 30 images) + `images[].classification` (AI-tagged: `BEDROOM` / `KITCHEN` / `LIVING_ROOM` / `BATHROOM` / `BALCONY` / …), floorplanImageUrls, photosCount
- **Tags** — isExclusive, has3DVisit, hasBrokerageFee, isNew
- **Agency** — agencyName, agencyType (Agence / Mandataire / Network), agencyProfileUrl, agencyWebsiteUrl, agencyFeeUrl, agencyImprintUrl, agencyLogoUrl, agencyAddress (street), agencyRcs, agencySiret, clientType (pro/particulier), clientId, publisherType, isPrivateOwner, phoneNumbers
- **Agency enrichment (when `enrichAgency: true`)** — agencyDescription (full bio), agencyServices, agencyOpeningHours (structured per day), agencyTeamMembers (with names + roles), agencyEmailAddresses, intermediaryType, network, spokenLanguages, memberships, social links
- **Timestamps** — createdAt, updatedAt (ISO)

***

### How a run works

1. **Paste URLs, get rows.** Search, listing and agency URLs in any mix; each one is recognised automatically. Leave `proxy` empty: the default works out of the box.
2. **Parallel by default.** Up to 10 property pages load at once (`maxConcurrency`). As soon as a search page comes back, its listings start loading while the next search page is fetched.
3. **One fetch per agency.** Each unique agency profile (`/professionnels-immobilier/{id}`) is fetched **once**, and every property from that agency reuses it. A 50-property batch from one agency costs one extra fetch, not 50.
4. **Automatic retries.** A page that fails to load is retried automatically, so a temporary error rarely costs you a row. A listing that no longer exists is named in the run's status message instead of failing the run.
5. **Search-page rows (optional).** With `scrapeDetails: false` the actor builds property rows from the search result pages alone, 30 properties per request, instead of opening each listing. Several times faster on big searches; the detail-only fields (listed under Input) stay empty.

***

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `startUrls` | `string[]` | **yes** | Any mix of search / detail / agency URLs. Auto-classified. Every filter in a pasted `/classified-search?…` URL is kept. A URL the actor cannot read (e.g. the WAF-blocked `/list.htm?…`) is skipped and named in the run's status message. |
| `scrapeDetails` | `boolean` | no | `true` (default): every row comes from the listing's own page. `false`: rows come from the search result pages alone, 30 per request. Empty in that mode: full description (cut at about 500 characters), `features`, `energySources`, `gesRating`, DPE kWh / CO₂ / annual energy cost, `notaryFees`, `totalProjectCost`, `monthlyMortgage`, co-ownership fields, `latitude` / `longitude`. Each row says which it got in `detailsScraped`. Detail and agency URLs always open each listing. |
| `enrichAgency` | `boolean` | no | When `true` (default), each unique agency profile is fetched once and merged into every property row from that agency. Adds `agencyAddress`, `agencyDescription`, `agencyServices`, `agencyOpeningHours`, `agencyTeamMembers`, `agencyLogoUrl`. |
| `maxItems` | `integer` | no | Hard cap on property rows. Agency-only rows do not count. Default `1000`. Free-plan runs are capped at `2`. |
| `maxConcurrency` | `integer` | no | Max parallel property fetches. Default `10`. |
| `minConcurrency` | `integer` | no | Default `1`. |
| `maxRequestRetries` | `integer` | no | Retry budget for the alternative pipeline (`useInternalHandler: false`). The default pipeline retries failed pages automatically. Default `5`. |
| `useInternalHandler` | `boolean` | no | `true` (default): the standard pipeline. `false`: an alternative pipeline kept for troubleshooting. Leave it on. |
| `proxy` | `object` | no | **Leave empty.** The default works out of the box. Apify Proxy groups set here (`RESIDENTIAL`, datacenter, or no proxy) are ignored; only your own proxy URLs replace the default. |

#### Example input

```json
{
    "startUrls": [
        "https://www.seloger.com/immobilier/achat/immo-paris-75/",
        "https://www.seloger.com/immobilier/locations/immo-paris-75/",
        "https://www.seloger.com/professionnels-immobilier/3XZa2Es7QReNKaxmQ8dWcC"
    ],
    "enrichAgency": true,
    "maxItems": 50
}
```

That yields up to **50 property rows** from the Paris listing (with the direct detail and agency URLs interleaved). One row per property, each enriched with the agency profile when `enrichAgency` is on.

***

### Output schema

Two row shapes, distinguishable by the presence of `kind: "agency"`:

#### Property row (one per property URL)

```json
{
  "propertyId": "274896393",
  "externalRef": "264MU5Q7CYFN",
  "title": "Appartement à vendre",
  "propertyType": "Appartement",
  "transactionType": "achat",
  "rooms": 2,
  "bedrooms": 1,
  "livingArea": 66,
  "floor": "4/4",
  "address": "Saint Thomas d'Aquin, Paris 7ème arrondissement (75007)",
  "neighborhood": "Saint Thomas d'Aquin",
  "city": "Paris 7ème arrondissement",
  "postalCode": "75007",
  "description": "Rue de Varenne, mitoyen de l'hôtel de Matignon, un atelier d'artiste au dernier étage d'un immeuble de style Directoi...",
  "features": [
    "Dernier étage, 4ème étage/4 étages",
    "Cuisine équipée, Cuisine ouverte"
  ],
  "constructionYear": null,
  "energySources": "Gaz",
  "dpeRating": "D",
  "gesRating": "D",
  "price": 1695000,
  "notaryFees": 135600,
  "totalProjectCost": 1830600,
  "monthlyMortgage": 8612,
  "coOwnershipLots": null,
  "coOwnershipChargesPerYear": 2932,
  "coOwnershipProceedings": "Pas de procédure en cours",
  "latitude": null,
  "longitude": [
    [
      [
        2.32416,
        48.85024
      ],
      [
        2.32401,
        48.85017
      ]
    ]
  ],
  "agencyName": "P B",
  "agencyType": "Proposé par une agence immobilière",
  "agencyProfileUrl": "https://www.seloger.com/professionnels-immobilier/LuiAdTBkt3sQQYyUoxjzaK",
  "agencyWebsiteUrl": "http://www.patrice-besse.com/",
  "agencyFeeUrl": "https://www.patrice-besse.com/mentions-legales/",
  "imageUrls": [
    "https://mms.seloger.com/e/d/1/1/ed11e149-7590-4004-9f8f-328a3a0142a5.jpg?ci_seal=e09dc47557dd82df4f9dfe9e82a989fab765...",
    "https://mms.seloger.com/7/7/7/8/77784c42-ac4b-4235-b87c-abbe08e0e661.jpg?ci_seal=cd9a76d1c79252e8f8725ba501b0e340cb5b..."
  ],
  "url": "https://www.seloger.com/annonces/achat/appartement/paris-7eme-75/saint-thomas-d-aquin/274896393.htm",
  "jsonLd": {
    "@context": "https://schema.org",
    "@type": "RealEstateListing",
    "datePosted": "2026-07-13T14:22:00.000Z",
    "description": "Rue de Varenne, mitoyen de l'hôtel de Matignon, un atelier d'artiste au dernier étage d'un immeuble de style Directoi...",
    "name": "Appartement à vendre T2/F2 66 m² 1695000 € Saint Thomas d'Aquin Paris (75007)",
    "itemOffered": {
      "@type": "APARTMENT",
      "name": "Appartement à vendre T2/F2 66 m² 1695000 € Saint Thomas d'Aquin Paris (75007)",
      "numberOfRooms": "2",
      "floorSize": {
        "@type": "QuantitativeValue",
        "value": "66",
        "unitCode": "MTK"
      }
    },
    "offers": {
      "@type": "Offer",
      "price": "1695000",
      "priceCurrency": "EUR",
      "availability": "https://schema.org/InStock"
    }
  },
  "headline": "Rue de Varenne, mitoyen de l'hôtel de Matignon, un atelier d'ar",
  "pricePerM2": "25 682 €/m²",
  "annualEnergyCost": null,
  "energyDiagnosticDate": "Après le 1er juillet 2021",
  "primaryEnergyKwh": "149 kWh/m².an",
  "finalEnergyKwh": null,
  "co2EmissionsKgPerM2": "31 kg CO₂/m².an",
  "dpeIndex": 3,
  "publisherType": "AGENCY",
  "isPrivateOwner": false,
  "phoneNumbers": [
    "+33 1 42 84 80 85"
  ],
  "agencyAddress": "7 rue Chomel, Paris 75007",
  "agencyImprintUrl": null,
  "agencyLegalInformations": [
    "Sarl P.B. SAS au capital de 9 147 €",
    "Carte professionnelle 7501 2017 000 016 72 délivrée par la Préfecture de Paris"
  ],
  "agencyRcs": null,
  "agencySiret": "34350396700048",
  "createdAt": "2026-07-13T14:22:00Z",
  "updatedAt": "2026-07-13T14:26:05.284Z",
  "tags": {
    "isExclusive": false,
    "has3DVisit": false,
    "hasBrokerageFee": false,
    "isNew": false
  },
  "rawPropertyType": "APARTMENT",
  "rawDistributionType": "BUY",
  "rawDistributionSubType": "RESALE",
  "geoIdHierarchy": [
    {
      "id": "AD09FR32",
      "typeKey": "AD09"
    },
    {
      "id": "AD08FR31096",
      "typeKey": "AD08"
    }
  ],
  "region": "Ile-de-France",
  "buildingState": null,
  "priceFormatted": "1 695 000 €",
  "plotSurface": null,
  "photosCount": 12,
  "clientType": "pro",
  "clientId": "RC-031771",
  "images": [
    {
      "url": "https://mms.seloger.com/e/d/1/1/ed11e149-7590-4004-9f8f-328a3a0142a5.jpg?ci_seal=e09dc47557dd82df4f9dfe9e82a989fab765...",
      "key": "ed11e149-7590-4004-9f8f-328a3a0142a5",
      "alt": "Appartement à vendre 1 695 000 € 2 pièces 1 chambre 66 m² Étage 4/4 Saint Thomas d'Aquin Paris 7ème arrondissement 75007",
      "classification": "EXTERIOR_VIEW"
    },
    {
      "url": "https://mms.seloger.com/7/7/7/8/77784c42-ac4b-4235-b87c-abbe08e0e661.jpg?ci_seal=cd9a76d1c79252e8f8725ba501b0e340cb5b...",
      "key": "77784c42-ac4b-4235-b87c-abbe08e0e661",
      "alt": null,
      "classification": "LIVING_ROOM"
    }
  ],
  "floorplanImageUrls": [],
  "transport": {
    "metro": [
      {
        "name": "12",
        "color": "#007a53"
      },
      {
        "name": "13",
        "color": "#71c5e8"
      }
    ],
    "bus": [
      {
        "name": "63",
        "color": "#cec92a"
      },
      {
        "name": "68",
        "color": "#ffbe02"
      }
    ]
  },
  "isAddressPublished": false,
  "country": "FRA",
  "agencyDescription": "Partout en France\r\nDepuis 1924, trois générations se sont succédé pour développer un réseau de vente national\r\nspécia...",
  "agencyServices": [
    "BUY SELL REAL ESTATE",
    "ESTIMATION"
  ],
  "agencyOpeningHours": [
    "Lundi: 10:00–13:00 / 14:00–19:00",
    "Mardi: 10:00–13:00 / 14:00–19:00"
  ],
  "agencyTeamMembers": [],
  "agencyLogoUrl": "https://mms.seloger.com/5/7/c/4/57c42c3a-c22b-41fe-9deb-bb38d6c075c1.jpg?ci_eqs=&ci_seal=52702b181ab560027a483437ef73...",
  "scrapedAt": "2026-08-17T15:29:00.361Z"
}
```

#### Agency row (one per agency URL, emitted only when an agency URL is in `startUrls`)

```jsonc
{
  "kind":                 "agency",
  "agencyId":             "FEW3VPchH8roDn265N8Hnj",
  "name":                 "IMOSS",
  "address":              "…",
  "description":          "…",
  "services":             ["…"],
  "openingHours":         ["…"],
  "teamMembers":          ["…"],
  "propertyUrls":         ["https://www.seloger.com/annonces/…/269476619.htm", "…"],
  "websiteUrl":           null,
  "profileUrl":           "https://www.seloger.com/professionnels-immobilier/FEW3VPchH8roDn265N8Hnj",
  "imageUrl":             "https://mms.seloger.com/…",
  "jsonLd":               { "@type": "RealEstateAgent", "name": "IMOSS", "address": "…", "image": "…" },
  "scrapedAt":            "2026-05-20T05:38:00.000Z"
}
```

When you paste an agency URL into `startUrls`, the actor emits this row and then enqueues **every property URL visible on the agency profile page** as a detail fetch — so one agency URL becomes 1 agency row + N property rows.

***

### ✨ Why use this scraper?

Trying to track the French property market without paying for a real-estate-data SaaS? Building a comp tool for a Paris arrondissement? Need clean DPE / GES energy-rating data for sustainable-finance work?

- 🇫🇷 **France-native.** French labels as SeLoger shows them, French currency / surface units (€ + m²) preserved verbatim.
- 🎯 **Three URL kinds, one actor.** Search URLs, individual property URLs, agency profile URLs — paste any mix and the actor classifies and routes each.
- 📋 **DPE / GES first-class.** Energy diagnostic letters (A–G) and construction year on every listing that shows them; most competitors skip this entirely.
- 📍 **Latitude / longitude** on every listing that shows its location on a map, whether as a pin or as an area.
- 🏢 **Per-agency cache.** Each unique agency profile is fetched once, even if 50 of your properties are from the same agency. Costs scale with unique agencies, not properties.
- 🧭 **Bad URLs caught early.** URL shapes SeLoger no longer serves (such as `/list.htm?…`) are skipped up-front and named in the run's status message, so a run never stalls on them.
- 🔁 **Automatic retries.** A page that fails to load is retried automatically, so a temporary error rarely costs you a row.
- 📤 **Clean exports.** Dataset rows are stable JSON; CSV export is generated automatically.

***

### 🎯 Use cases

| Team | What they build |
|------|-----------------|
| **Real-estate analysts** | Price-per-m² dashboards by arrondissement, neighborhood, DPE rating |
| **Investors / property funds** | Daily new-listing feeds for buy-to-let or value-add acquisitions |
| **PropTech startups** | Comparable-sales engines fed by a clean French listing dataset |
| **Sustainable-finance teams** | DPE / GES distributions across Paris / Lyon / Marseille — input to green-mortgage products |
| **Mortgage brokers** | Lead pipelines from new high-end listings (`monthlyMortgage` + `notaryFees` already computed) |
| **Agencies (competitive intel)** | What's listed where, by which competitor, at what price |
| **Journalists / researchers** | Longitudinal datasets on FR housing-market shifts |

***

### Notes & limitations

- **Leave `proxy` empty.** The default works out of the box and is what the actor is tested with. Apify Proxy groups are ignored; your own proxy URLs replace the default only when you supply them.
- **`imageUrls` can hold only part of the carousel** on some listings, typically the first 1–3 images. The hero image is always present.
- **Phone numbers are not extracted.** SeLoger shows the direct-dial number only after a "Show number" click. Email and contact-form CTAs are reachable; the agency profile URL is always present and contains opening hours + website.
- **Pagination stops on empty page.** SeLoger doesn't show a total-page count — the actor follows `?page=N` on `/classified-search` (SEO listings continue there after page 1) until a page returns zero property cards.
- **The `/list.htm?projects=…` URL shape no longer works on SeLoger** and is skipped. Paste the `/recherche/…` or `/classified-search?…` URL your browser shows instead.
- **Agency URL must be the new shape** `/professionnels-immobilier/{opaque-id}`. The old `/professionnels/agences-immobilieres/{city-slug}/` city-directory URL returns 404 today and is rejected.

***

### Free tier

You can run this scraper on a free Apify account before paying anything:

| | Free account |
|---|---|
| Results per run | up to **2** |
| Start URLs per run | **1** |
| Cost | nothing — the free plan includes monthly platform credit |

That is enough to check the field list and the data quality against your own URL. Paid plans lift both caps; see [Apify pricing](https://apify.com/pricing).

### Support

Issues, feature requests, or custom output shapes? Open a ticket on the actor's [Apify Console issues page](https://console.apify.com/actors/) or message the maintainer.

***

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/seloger-scraper`).

**Purpose:** Extract SeLoger.com property listings, individual property pages, and agency profiles across France, with 75+ fields per row.

**Minimal input:**

```json
{
  "startUrls": ["https://www.seloger.com/immobilier/achat/immo-paris-75/"],
  "maxItems": 50
}
```

Alternatively, leave `startUrls` empty and build a search from filters: set `locations` (place names as you would type them in SeLoger's search box, such as `Cergy`, `Marseille 7ème` or `13007`, or place IDs such as `AD08FR31096`) plus `distributionType` (`Buy`/`Rent`/`Buy_Auction`), and optionally `estateTypes`, `priceMin`, `priceMax`, `roomsMin`. Names are looked up with SeLoger's own place search; the run log shows the place each one matched, and a name SeLoger does not know is named in the run's status message. Or set `instantDatabase: true` with the `db*` filters to return pre-collected agencies with no scraping.

**Output:** one dataset row per property — propertyId, externalRef, title, propertyType, transactionType, rooms, bedrooms, livingArea, floor, address, neighborhood, city, postalCode, region, country, price, priceFormatted, pricePerM2, notaryFees, totalProjectCost, monthlyMortgage, dpeRating, gesRating, primaryEnergyKwh, co2EmissionsKgPerM2, latitude, longitude, agencyName, agencyType, agencyProfileUrl, agencyAddress, phoneNumbers, features, imageUrls, images (each with `classification`), transport (metro/bus/tramway/RER), tags, url, scrapedAt. Agency URLs additionally emit an agency row carrying `kind: "agency"`.

**Behaviors an agent should know:**

- Always set `maxItems` (default 1000; agency-only rows do not count). Each `/classified-search?` URL caps at ~370 properties; enable `splitByPrice` to run 5 price bands for ~1,850 (cost scales ~5×).
- `startUrls` takes precedence — when any URL is supplied, all filter fields (`locations`, `distributionType`, etc.) are ignored.
- Four URL kinds auto-classify: search page (`/recherche/…` or `/immobilier/…`), `/classified-search?` filter search, property detail (`/annonce/…` or `….htm`), agency profile (`/professionnels-immobilier/{id}`). The old `/list.htm?projects=…` shape no longer works on SeLoger; it and any other unreadable input are skipped and named in the run's status message.
- Leave `proxy` empty: the default works out of the box. Apify Proxy groups passed in `proxy` are ignored; only your own proxy URLs replace the default.
- `enrichAgency` (default true) fetches each agency profile once, cached, and merges it into every property row from that agency. `enrichEmails` (default false) is billed per contact email found, only on a hit, never for misses.
- The direct-dial phone number is not in the row, and `imageUrls` can hold only part of the carousel (the hero image is always present).

***

### ⚠️ Disclaimer

This Actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by** SeLoger.com, AVIV Group, Axel Springer SE, or any of their subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper extracts only **publicly visible** data from SeLoger.com — property listings, individual property pages, and agency profiles as they appear to any logged-out visitor. It does not log in and does not read private or authenticated pages. It caps how many pages it opens at once to avoid burdening SeLoger's infrastructure.

Users are responsible for:

- Complying with SeLoger.com's Terms of Service and French law (loi Hoguet, Code de la consommation, RGPD)
- Following GDPR / French CNIL guidance when storing or processing data about private individuals (vendors, agents)
- Not contacting agents, vendors, or team members listed in scraped data without their consent
- Not republishing scraped data in a way that competes commercially with SeLoger or misrepresents listing authorship
- Honouring any opt-out signals or `noindex` directives on the source pages
- Refreshing scraped data regularly — property availability, prices, and energy ratings change frequently

***

### SEO Keywords

seloger scraper, scrape seloger, seloger.com scraper, seloger api, seloger immobilier scraper, scraping seloger, seloger.fr scraper, french real estate scraper, paris property scraper, immobilier scraper, scrape paris real estate, paris listings scraper, france real estate api, real estate france scraper, seloger achat scraper, seloger location scraper, seloger annonces scraper, seloger agences scraper, french housing data scraper, DPE scraper, GES scraper, energy rating scraper, real estate listings france, french property data, real estate market data france, paris housing market scraper, real estate analytics france, comparable sales scraper france, seloger.com data extraction, french housing market api, real estate intelligence france, Apify seloger, french rental market, paris rental scraper, neuf scraper, viager scraper, colocation scraper, prestige scraper, french property investment, parisian real estate, real estate lead generation france, agent immobilier scraper, agence immobilière scraper, ile-de-france property scraper, lyon property scraper, marseille property scraper, bordeaux property scraper

***

#### 💬 Support

- For issues or feature requests, please use the **Issues** tab on the actor's Apify Console page.
- Author's website: <https://muhamed-didovic.github.io/>
- Email: <muhamed.didovic@gmail.com>

#### 🛠 Additional services

- Custom output shape, additional fields, or a private build: <muhamed.didovic@gmail.com>
- Need other DACH property platforms (Immowelt, Immonet, Immobilien.de, Wohnungsbörse, Comparis, Homegate, willhaben.at)? Drop an email — most are already in the [portfolio](https://apify.com/memo23).
- For API access (no Apify fee, just a usage fee for the API): <muhamed.didovic@gmail.com>

#### 🔎 Explore more scrapers

If this SeLoger scraper was useful, see other real-estate scrapers at [memo23's Apify profile](https://apify.com/memo23) — Immowelt (DE), Immonet (DE), Immobiliare (IT), Immoweb (BE), LoopNet US + UK, Rightmove UK, and more.

# Actor input Schema

## `startUrls` (type: `array`):

Accepted URL shapes:
• Search page as SeLoger's address bar shows it — `/recherche/{transaction}/{type}/…/{place-id}` (e.g. `/recherche/achat/appartement/ile-de-france/paris-75000/ad08fr31096`), or the older `/immobilier/{transaction}/immo-{city-dept}/[bien-{type}/]` that redirects there (e.g. `/immobilier/achat/immo-paris-75/`; rentals are `/immobilier/locations/immo-paris-75/`, plural). SeLoger shows only page 1 of these, so the actor continues on the equivalent `/classified-search` search, newest first.
• Filter search — `/classified-search?distributionTypes=…&locations=…&priceMax=…&numberOfRoomsMin=…`. Every filter in a pasted URL is kept (rooms, bedrooms, surface, energy class, furnished, …). Paginates via `?page=N`.
• Property detail — `/annonce/{transaction}/{region}/{dept}/{city}/{id}` or `/annonces/{type}/{slug}/{city-dept}[/{neighborhood}]/{id}.htm`.
• Agency profile — `/professionnels-immobilier/{opaque-id}`. Emits one agency row + every property the agency has listed.

The older `/list.htm?projects=…` query-style URL is WAF-blocked and rejected.

## `locations` (type: `array`):

Place names as you would type them in SeLoger's search box: a town (`Cergy`), an arrondissement (`Marseille 7ème`), a postcode (`13007`), a département (`Rhône`) or a region, **or** a raw SeLoger place ID (e.g. `AD08FR31096`). Names are looked up with SeLoger's own place search, and the run log shows the place each one matched. A name SeLoger does not know is skipped and named in the run's status message. Multiple locations search the union.

## `distributionType` (type: `string`):

Buy = achat, Rent = location, Buy_Auction = vente aux enchères.

## `estateTypes` (type: `array`):

Filter by property type. Leave empty for both Apartment + House.

## `priceMin` (type: `integer`):

Lower price bound in euros. Leave empty for no lower bound.

## `priceMax` (type: `integer`):

Upper price bound in euros. Leave empty for no upper bound.

## `roomsMin` (type: `integer`):

Minimum number of rooms (pièces). 1 = studio, 2 = 1-bed, 3 = 2-bed, etc.

## `splitByPrice` (type: `boolean`):

SeLoger caps every `/classified-search?` URL at ~20 pages × ~20 = **~370 properties**. Enable splitting to run 5 narrower searches in one go — each gets its own page-20 budget, multiplying total yield to **~1,850 properties**. Cost scales ~5× because each band is a separate set of fetches.

Default bands (log-distributed for the FR market): \[0–200K], \[200K–400K], \[400K–700K], \[700K–1.2M], \[1.2M+]. If you supplied `priceMin`/`priceMax` above, the user range is split into 5 equal bands instead.

## `scrapeDetails` (type: `boolean`):

On (default): every property row comes from the listing's own page, with all fields. Off: rows are built from the search result pages alone, 30 properties per request, so large searches finish several times faster. Off leaves these fields empty: full description (cut at about 500 characters), features list, energy source, GES rating, DPE kWh / CO₂ / annual energy cost, notary fees, total project cost, monthly mortgage, co-ownership lots / charges / proceedings, and GPS coordinates. Price, rooms, surface, floor, DPE letter, photos, address, transport, and the agency name, phone, SIRET and website are still there. Applies to search URLs and filters; listing and agency URLs always open each listing.

## `enrichAgency` (type: `boolean`):

When enabled, each unique agency profile (`/professionnels-immobilier/{id}`) is fetched once and merged into every property row from that agency — adds `agencyAddress`, `agencyDescription`, `agencyServices`, `agencyOpeningHours`, `agencyTeamMembers`, `agencyLogoUrl`. Cached per agency, so a 50-property batch from one agency costs one extra fetch.

## `enrichEmails` (type: `boolean`):

If enabled, finds a contact email for each result from its own website (or by discovering it from the name). Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Billed per contact email found; only charged when an email is returned, never for misses.

## `instantDatabase` (type: `boolean`):

Return pre-collected French real-estate agencies (name, address, phone, email, website, SIRET/RCS, socials) straight from our accumulated database instead of scraping live. Instant, no proxy. Combine with the db\* filters below.

## `dbName` (type: `string`):

Instant-database mode only: return only agencies whose name contains this text (e.g. 'Century 21').

## `dbNetwork` (type: `string`):

Instant-database mode only: return only agencies in a network matching this text (e.g. 'Orpi', 'Laforêt').

## `dbHasPhone` (type: `boolean`):

Instant-database mode only: return only agencies that have a phone number.

## `dbHasEmail` (type: `boolean`):

Instant-database mode only: return only agencies that have an email.

## `maxItems` (type: `integer`):

Hard cap on the number of rows saved to the dataset. Every saved row (property, agency, or instant-database) counts toward this cap and is billed as a result.

## `maxConcurrency` (type: `integer`):

Maximum number of property pages processed in parallel.

## `minConcurrency` (type: `integer`):

Minimum number of pages processed in parallel.

## `maxRequestRetries` (type: `integer`):

Retry budget for the legacy pipeline. The default pipeline retries failed pages automatically.

## `proxy` (type: `object`):

Leave empty: the default works out of the box. Apify Proxy groups chosen here (RESIDENTIAL, datacenter, or no proxy) are ignored. Only your own proxy URLs replace the default.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.seloger.com/immobilier/achat/immo-paris-75/",
    "https://www.seloger.com/classified-search?classifiedBusiness=Private&distributionTypes=Buy&estateTypes=House,Apartment&locations=AD08FR1977&priceMax=300000&priceMin=100000&order=DateDesc",
    "https://www.seloger.com/immobilier/locations/immo-paris-75/",
    "https://www.seloger.com/professionnels-immobilier/3XZa2Es7QReNKaxmQ8dWcC"
  ],
  "locations": [
    "Paris"
  ],
  "distributionType": "Buy",
  "splitByPrice": false,
  "scrapeDetails": true,
  "enrichAgency": true,
  "enrichEmails": false,
  "instantDatabase": false,
  "dbHasPhone": false,
  "dbHasEmail": false,
  "maxItems": 1000,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 5
}
```

# 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 = {
    "startUrls": [
        "https://www.seloger.com/immobilier/achat/immo-paris-75/",
        "https://www.seloger.com/classified-search?classifiedBusiness=Private&distributionTypes=Buy&estateTypes=House,Apartment&locations=AD08FR1977&priceMax=300000&priceMin=100000&order=DateDesc",
        "https://www.seloger.com/immobilier/locations/immo-paris-75/",
        "https://www.seloger.com/professionnels-immobilier/3XZa2Es7QReNKaxmQ8dWcC"
    ],
    "locations": [
        "Paris"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/seloger-scraper").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 = {
    "startUrls": [
        "https://www.seloger.com/immobilier/achat/immo-paris-75/",
        "https://www.seloger.com/classified-search?classifiedBusiness=Private&distributionTypes=Buy&estateTypes=House,Apartment&locations=AD08FR1977&priceMax=300000&priceMin=100000&order=DateDesc",
        "https://www.seloger.com/immobilier/locations/immo-paris-75/",
        "https://www.seloger.com/professionnels-immobilier/3XZa2Es7QReNKaxmQ8dWcC",
    ],
    "locations": ["Paris"],
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/seloger-scraper").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 '{
  "startUrls": [
    "https://www.seloger.com/immobilier/achat/immo-paris-75/",
    "https://www.seloger.com/classified-search?classifiedBusiness=Private&distributionTypes=Buy&estateTypes=House,Apartment&locations=AD08FR1977&priceMax=300000&priceMin=100000&order=DateDesc",
    "https://www.seloger.com/immobilier/locations/immo-paris-75/",
    "https://www.seloger.com/professionnels-immobilier/3XZa2Es7QReNKaxmQ8dWcC"
  ],
  "locations": [
    "Paris"
  ]
}' |
apify call memo23/seloger-scraper --silent --output-dataset

```

## MCP server setup

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

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/ALyusKIkWXQdEn9lo/builds/ANDU3ihpGJXaBxjcb/openapi.json
