# SeLoger Scraper — France Property for Sale & Rent (`tortuga/seloger-scraper`) Actor

Scrape SeLoger.com listings for sale or rent from search URLs or city/postcode + filters: price, €/m², surface, rooms, floor, DPE/GES, features, photos, agency, coordinates.

- **URL**: https://apify.com/tortuga/seloger-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Scraper — France Property for Sale & Rent

Scrape property listings from SeLoger.com, France's leading real estate portal (same group as Logic-Immo and Belles Demeures), for sale (achat) or for rent (location). For each listing you get the price, the price per m², the living surface and plot size, the number of rooms (pièces), bedrooms (chambres) and the floor. You also get the property type, whether it is a new build (neuf), the DPE energy class, the year built, and the city, postcode, district, department and region. Every photo URL comes too, plus the agency (or "private seller"), the publication and update dates and the listing URL.

Start from any SeLoger search URL, or type a city, postcode, arrondissement, department or region and pick filters (price, surface, rooms, bedrooms, property type, new build, must-have features, private or professional seller). Turn on **Include full details** to also get the full description, the map coordinates, every feature (lift, balcony, terrace, garden, parking, cellar, pool, furnished...), the DPE and GES classes with their kWh and CO₂ values, the energy-bill estimate, the rent breakdown (charges, deposit, tenant fees), the notary-fee estimate and the co-ownership details (lots, yearly charges).

The actor reads the same JSON services the SeLoger website loads, not the rendered HTML. That keeps the output complete and stable and the runs fast: 1,000 listings in 45 seconds in our test. You pay only for the listings you get.

### What data does SeLoger Scraper extract?

| Field | Description |
|---|---|
| `id`, `legacyId`, `url` | SeLoger listing id (e.g. `26CS6LJJU2XE`), the old numeric reference, and the listing URL |
| `title`, `headline` | SeLoger's title (`"Appartement à vendre"`) and the advertiser's headline (`"F2 au calme"`) |
| `transactionType` | `sale` or `rent` |
| `propertyType`, `propertyTypeCode` | `"Appartement"` / `APARTMENT`, `"Maison"` / `HOUSE`, `"Programme immobilier"`, ... |
| `price`, `priceText`, `priceOnRequest` | Sale price, or monthly rent for rentals, in euros (`null` and `priceOnRequest: true` for "Prix sur demande") |
| `pricePerSqm`, `priceInfo` | Price per m² as SeLoger shows it (computed from price and surface when not shown); `priceInfo` is e.g. `"charges comprises"` for rents |
| `surface`, `landSurface` | Living surface and plot (terrain) in m² |
| `rooms`, `bedrooms` | Pièces and chambres |
| `floor`, `floorNumber`, `buildingFloors` | `"Étage 2/5"` -> 2 and 5; `"RDC"` -> 0 |
| `availability` | For rentals: `"disponible dès maintenant"`, `"dès le 01/11/2026"` |
| `energyClass`, `yearBuilt`, `condition` | DPE letter (A-G), year of construction, building condition (`REFURBISHED`, `NEED_OF_RENOVATION`, ...) when given |
| `isNewBuild`, `newBuildProgram`, `newBuildProgramUrl` | New-build (neuf) listings and their programme |
| `city`, `postcode`, `district`, `department`, `region`, `country` | e.g. `Paris 18ème arrondissement`, `75018`, `Grandes Carrières-Clichy`, `Paris`, `Ile-de-France` |
| `transport` | Nearest metro / tram / bus lines shown on the listing |
| `description`, `descriptionTruncated` | The description; in search results SeLoger cuts it after ~500 characters (`descriptionTruncated: true`), with full details it is complete |
| `photos`, `photoCount`, `hasVirtualTour` | All photo URLs; whether there is a 3D / video tour |
| `isExclusive`, `isNewListing` | Exclusive mandate badge; SeLoger's "new" badge |
| `sellerType` | `professional` or `private` (particulier) |
| `agencyName`, `agencyProfileUrl`, `agencyWebsite`, `agencyLogo`, `agencyAddress`, `agencyLegalInfo`, `agencyFeesUrl` | The agency as shown on the listing (business data: name, SeLoger page, website, office address, RCS/SIRET lines, fee schedule) |
| `contactName` | For private sellers: the first name shown on the listing |
| `createdAt`, `updatedAt` | Publication and last update (ISO, UTC) |
| `searchUrl`, `position`, `scrapedAt` | The search the listing came from (as a SeLoger URL), its rank, the time of the run |

With **Include full details** you also get:

| Field | Description |
|---|---|
| `description` | Full description text (line breaks kept) |
| `latitude`, `longitude`, `locationPrecision` | Map point: `exact` (address published), `approximate` (private sellers: rounded to ~1 km), or `area` (centre of the town / district when no address is published) |
| `features` | Every feature line of the listing, e.g. `["Ascenseur", "Cave (Total 3 m²)", "Exposition: ouest", "Digicode", "Pas de balcon"]` |
| `hasElevator`, `hasBalcony`, `hasTerrace`, `hasGarden`, `hasParking`, `hasCellar`, `hasPool`, `isFurnished` | `true` / `false` when the listing says so ("Ascenseur" / "Pas d'ascenseur"), `null` when it does not mention it |
| `dpeClass`, `gesClass`, `energyConsumption`, `ghgEmissions` | DPE and GES letters, primary energy in kWh/m²/year, emissions in kg CO₂/m²/year |
| `energyCostEstimate`, `dpeDate`, `energySources` | e.g. `"entre 910 et 1290 €/an"`, `"Après le 1er juillet 2021"`, `"Gaz"` |
| `rentIncludingCharges`, `rentExcludingCharges`, `monthlyCharges`, `rentSupplement`, `deposit`, `tenantFees` | Rentals: the rent breakdown, deposit (dépôt de garantie) and agency fees charged to the tenant |
| `notaryFeesEstimate` | Sales: SeLoger's notary-fee estimate |
| `coOwnershipLots`, `coOwnershipAnnualCharges`, `coOwnershipProceedings` | Copropriété: number of lots, yearly charges, procedures in progress |
| `priceLines` | Every price line of the listing as label -> amount |
| `detailsFetched`, `detailError` | Whether the details were loaded, and why not |

### How to scrape SeLoger listings

1. Open [seloger.com](https://www.seloger.com/), search for a place, set your filters (price, surface, rooms, property type, sort, ...) and copy the address from your browser. Or skip this step: type places in **Locations** and pick the filters in the input.
2. Paste the URL into **Start URLs**. You can add several searches, SEO search pages (`/recherche/...`) and single listing URLs (`/annonce/...`).
3. Set **Max items** and start the run. Download the results as JSON, CSV or Excel, or read them through the API.

Every SeLoger filter works through a search URL (energy class, floor, build state, ...). The Locations search covers the common ones: buy or rent, property types, price, surface, rooms, bedrooms, land surface, new build, must-have features and seller type.

### Input example

```json
{
  "locations": ["Paris 11e", "Paris 12e"],
  "transactionType": "rent",
  "propertyTypes": ["apartment"],
  "maxPrice": 1800,
  "minSurface": 35,
  "minRooms": 2,
  "features": ["elevator"],
  "sort": "newest",
  "maxItems": 500,
  "includeDetails": true
}
```

Or with URLs:

```json
{
  "startUrls": [
    { "url": "https://www.seloger.com/classified-search?distributionTypes=Buy&estateTypes=House&locations=AD06FR34&priceMax=400000&numberOfBedroomsMin=3" },
    { "url": "https://www.seloger.com/recherche/location/appartement/auvergne-rhone-alpes/lyon-69000/ad08fr28808" },
    { "url": "https://www.seloger.com/annonce/achat/ile-de-france/paris-75/paris-75000/26CS6LJJU2XE" }
  ],
  "maxItems": 1000
}
```

Locations accept a city (`Bordeaux`), a postcode (`33000`), an arrondissement (`Paris 11e`, `Lyon 3e`), a neighbourhood (`Montmartre`), a department (`Gironde`) or a region (`Bretagne`). Each one is looked up with SeLoger's own place search; the `resolvedLocations` entry of the SUMMARY record in the key-value store shows which place was used.

### Output example

```json
{
  "id": "26CS6LJJU2XE",
  "legacyId": "281958781",
  "url": "https://www.seloger.com/annonce/achat/ile-de-france/paris-75/paris-75000/26CS6LJJU2XE",
  "title": "Appartement à vendre",
  "headline": "F2 au calme",
  "transactionType": "sale",
  "propertyType": "Appartement",
  "price": 400000,
  "priceText": "400 000 €",
  "pricePerSqm": 8888.89,
  "surface": 45,
  "rooms": 2,
  "bedrooms": 1,
  "floor": "Étage 2/5",
  "floorNumber": 2,
  "buildingFloors": 5,
  "energyClass": "D",
  "yearBuilt": 1880,
  "condition": "REFURBISHED",
  "isNewBuild": false,
  "city": "Paris 18ème arrondissement",
  "postcode": "75018",
  "district": "Grandes Carrières-Clichy",
  "department": "Paris",
  "region": "Ile-de-France",
  "transport": [{ "type": "METRO", "lines": ["13"] }, { "type": "BUS", "lines": ["21", "31", "54"] }],
  "photos": ["https://cdnihddipa.cloudimg.io/5/8/e/a/58ea3b08-30a3-4ef0-899a-b815808d1e60.jpg?ci_seal=45996f3d10027508f42164114865cf5783de651c"],
  "photoCount": 13,
  "hasVirtualTour": true,
  "isExclusive": true,
  "sellerType": "professional",
  "agencyName": "IMOSS",
  "agencyProfileUrl": "https://www.seloger.com/professionnels-immobilier/FEW3VPchH8roDn265N8Hnj",
  "agencyWebsite": "https://www.imossimmobilier.fr/",
  "createdAt": "2026-10-09T10:58:00Z",
  "updatedAt": "2026-10-10T00:56:39.86Z",
  "detailsFetched": true,
  "description": "Situé rue Lamarck, à quelques pas du métro Lamarck - Caulaincourt (ligne 12), venez vite découvrir votre futur nid douillet...",
  "latitude": 48.891108,
  "longitude": 2.328854,
  "locationPrecision": "exact",
  "features": ["Calme", "Exposition: ouest", "2ème étage/5 étages", "Pas d'ascenseur", "Cuisine séparée, Cuisine intégrée", "Cave (Total 3 m²)", "Pas de balcon", "Digicode"],
  "hasElevator": false,
  "hasBalcony": false,
  "hasCellar": true,
  "dpeClass": "D",
  "gesClass": "D",
  "energyConsumption": 204,
  "ghgEmissions": 44,
  "energyCostEstimate": "entre 910 et 1290 €/an",
  "notaryFeesEstimate": 32000,
  "coOwnershipLots": 40,
  "coOwnershipAnnualCharges": 1376,
  "searchUrl": "https://www.seloger.com/classified-search?distributionTypes=Buy&estateTypes=Apartment&locations=AD08FR31096&order=DateDesc",
  "position": 1,
  "scrapedAt": "2026-10-10T03:25:07Z"
}
```

(Shortened: real items carry every field from the tables above. Detail fields are absent when **Include full details** is off.)

### How many listings can I get per search?

SeLoger serves at most **10,000 listings per search**. When a search has more and **Max items** asks for more, the actor cuts it into price bands of up to 10,000 listings each, using a few tiny count requests, and collects them all. Results then come band by band, cheapest band first, and each band keeps your sort order. Listings without a price ("Prix sur demande") are not in any price band. Turn off **Split searches over 10,000 results** to stop at the first 10,000. For whole regions or all of France (400,000+ apartments for sale), split the work yourself by department or city.

### Does it work without login? Does it collect phone numbers?

No login and no account are needed: the actor reads only what anyone sees on SeLoger. It does **not** export phone numbers, which SeLoger shows only after a click. Private sellers' exact location is never exported: when SeLoger has a map point for a private seller's listing, it is rounded to about 1 km. When no address is published, the coordinates are the centre of the town or district (`locationPrecision: "area"`). Agencies' names, offices, websites and legal details are business data and are included. For private sellers, `contactName` is the first name the listing shows publicly.

### Do I need a proxy?

Yes. SeLoger is protected by DataDome, which refuses datacenter IP addresses. The default proxy, Apify **Residential** proxy in France, worked in all our test runs; a refused request (about 1 in 8 for searches, about 1 in 4 for listing details) is retried automatically on a new IP, and every run finished without errors. Residential traffic is billed by Apify per GB, and this actor uses little of it: about 1.5 MB per 1,000 listings, and about 23 MB per 1,000 listings with full details.

### Monitor changes on a schedule

Turn on **Only new or changed items** to watch a search. Each run remembers what earlier runs returned and outputs only new listings and listings whose price changed. Unchanged listings are dropped before any detail request, so they are not charged. **Max items** then sets how many listings are checked per run; keep the "Newest first" sort, e.g. 100-300 for a city or arrondissement. Save the input as a task in Apify and add a Schedule (for example daily). Give each watch its own **Monitoring key** if several schedules use the same search. Every output item gets `changeType` (`new` or `changed`), and changed items get `previousValues` with the old values, e.g. `{"price": 420000}`. The actor also remembers a few listings just below the window without outputting or charging them, so an older listing that moves into the window is not reported as new. Sold or removed listings simply stop appearing.

### Pricing

Pay per result: you are charged for each listing saved to the dataset, plus a small extra per listing when **Include full details** is on. See the Pricing tab for the current prices. There is no start fee. Platform usage is small: at the default 512 MB memory our test runs used about $0.02 per 1,000 listings (residential proxy, compute and dataset writes), and about $0.22 per 1,000 listings with full details (detail requests are paced at two at a time, so those runs take longer: about one listing per second).

### Integrations and API

Run it from the Apify API or a schedule, and send the results to Google Sheets, Slack, Make, Zapier, n8n or a webhook. Use `maxItems` to cap the cost of each run. Typical uses: price per m² studies by arrondissement or town, rental yield analysis, DPE / energy-class statistics (passoires thermiques), agency inventory tracking, new-listing alerts and lead lists of real estate agencies.

### Is it legal to scrape SeLoger?

This actor collects publicly visible listing data that anyone can see on SeLoger without logging in. It does not log in, it does not collect phone numbers or anything else behind a click, and it does not export private sellers' exact location. Private sellers' first names are personal data under the GDPR: you are responsible for having a legitimate purpose and a legal basis for processing them, and for respecting SeLoger's terms of use. If in doubt, ask a lawyer.

### Support

Found a bug or need a field that is not there? Open an issue on the Issues tab with the input you used and the run link.

# Actor input Schema

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

SeLoger search URLs with any filters set on the site (run the search on seloger.com and copy the address bar, e.g. https://www.seloger.com/classified-search?distributionTypes=Rent\&estateTypes=Apartment\&locations=AD08FR28808\&priceMax=1200), SEO search pages (https://www.seloger.com/recherche/...), or single listing URLs (https://www.seloger.com/annonce/...). Leave empty if you use Locations below.

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

Cities, postcodes, Paris/Lyon/Marseille arrondissements, neighbourhoods, departments or regions, one per line, e.g. 'Bordeaux', '75011', 'Paris 11e', 'Montmartre', 'Gironde', 'Bretagne'. Each is looked up with SeLoger's own place search; all places go into one combined search (like picking several places on the site).

## `transactionType` (type: `string`):

Listings for sale (achat) or for rent (location). Applies to Locations searches; start URLs keep their own.

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

Only these property types. Leave empty for apartments and houses (the site's default).

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

Minimum sale price, or minimum monthly rent for rentals, in euros.

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

Maximum sale price, or maximum monthly rent for rentals, in euros.

## `minSurface` (type: `integer`):

Minimum living surface in square metres.

## `maxSurface` (type: `integer`):

Maximum living surface in square metres.

## `minRooms` (type: `integer`):

Minimum number of rooms (pièces, as counted in France: living room + bedrooms).

## `maxRooms` (type: `integer`):

Maximum number of rooms (pièces).

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

Minimum number of bedrooms.

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

Maximum number of bedrooms.

## `minLandSurface` (type: `integer`):

Minimum plot (terrain) size in square metres, for houses and land.

## `newBuild` (type: `string`):

Only new-build listings (programmes neufs), exclude them, or both. 'Only' works for purchases.

## `features` (type: `array`):

Only listings that have all of these (SeLoger's own filters).

## `sellerType` (type: `string`):

Private sellers (particuliers), professionals (agencies, developers), or both.

## `sort` (type: `string`):

Order of the results. Applies to Locations searches and to start URLs that have no order of their own. 'Newest first' is best for monitoring; 'Relevance' is SeLoger's default order.

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

Stop after this many listings in total (across all searches). Keeps cost predictable. SeLoger serves at most 10,000 listings per search; larger searches are split into price bands automatically (see below).

## `maxItemsPerSearch` (type: `integer`):

Optional cap per start URL / location search, so one big search does not use up Max items before the others run.

## `includeDetails` (type: `boolean`):

Also load each listing's own record: full description, map coordinates, all features (lift, balcony, terrace, garden, parking, cellar, pool, furnished...), DPE and GES classes with their kWh / CO₂ values and energy-bill estimate, rent breakdown (rent without charges, charges, deposit, tenant fees), notary-fee estimate and co-ownership details. One small extra request per listing; charged as an extra 'detail' event (see pricing).

## `splitLargeSearches` (type: `boolean`):

SeLoger serves at most 10,000 listings per search. When a search has more and Max items asks for more, cut it into price bands of up to 10,000 listings (a few tiny count requests) so you can get every listing. Results then come band by band, cheapest band first; listings without a price are not in any band.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. With this on, Max items is the number of listings checked per run (e.g. the newest 200).

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input

## `proxyConfiguration` (type: `object`):

SeLoger is protected by DataDome, which refuses datacenter IPs. Apify RESIDENTIAL proxy (France) is the default and worked in every test run (refused requests are retried on a new IP). Residential traffic is billed by Apify per GB: this actor uses about 1.5 MB per 1,000 listings, and about 23 MB per 1,000 listings with full details.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.seloger.com/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08FR28808&priceMax=1200"
    }
  ],
  "transactionType": "buy",
  "newBuild": "any",
  "sellerType": "any",
  "sort": "newest",
  "maxItems": 100,
  "includeDetails": false,
  "splitLargeSearches": true,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}
```

# Actor output Schema

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

No description

# 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": [
        {
            "url": "https://www.seloger.com/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08FR28808&priceMax=1200"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "FR"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/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": [{ "url": "https://www.seloger.com/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08FR28808&priceMax=1200" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "FR",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/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": [
    {
      "url": "https://www.seloger.com/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08FR28808&priceMax=1200"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}' |
apify call tortuga/seloger-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tortuga/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/FFp1wk53xPC68Jn8q/builds/cpBtgOTrGZuDwaQ5B/openapi.json
