# Bien'ici Scraper \[$1/1K💰] | French Real Estate & DPE Data (`ahmed_jasarevic/bienici-scraper`) Actor

Scrape bienici.com French property listings: price, price per m², surface, rooms, DPE/GES energy classes, agency and coordinates. Ideal for real-estate market research, valuation and price monitoring in France.

- **URL**: https://apify.com/ahmed_jasarevic/bienici-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

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

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

## Bien'ici Scraper: French Real Estate Listings & DPE Data

Scrape real-estate listings from **bienici.com** (Bien'ici), one of France's largest property portals backed by the FNAIM agency network, and export price, price per m², surface, rooms/bedrooms, DPE/GES energy classes, GPS coordinates, city/district, agency names, photos and full descriptions as clean structured JSON. It calls Bien'ici's own internal JSON API, so no browser is needed and runs are cheap.

Built for French real-estate investors, proptech and valuation tools, and agency lead-generation teams who need `données immobilières` from buy or rent searches.

### Main use cases

- **Marché immobilier research**: analyze asking prices, price per m² and inventory by city, district and department.
- **Property and valuation data**: build a structured dataset of French listings with surface, rooms and DPE/GES energy classes.
- **Real estate lead generation**: pull agency names and contacts from active listings for outreach and partner research.
- **Price and DPE monitoring**: schedule recurring snapshots to track price changes (`priceHasDecreased`) and energy-class distribution.
- **Comp and estimation tooling**: filter by price, surface, rooms and property type to line up comparables for `estimation immobilière`.
- **Proptech and market datasets**: assemble buy or rent listings for analytics, dashboards and market reports.

### How it works

Bien'ici is a client-side SPA, so the served HTML contains no listings. Instead of rendering the page, this actor calls **Bien'ici's own internal JSON API**, the exact endpoints the site's frontend uses. Both are plain, unauthenticated JSON endpoints that are **not** Cloudflare-walled and need **no cookies and no browser**:

| Step | Endpoint | Purpose |
|---|---|---|
| Geo resolution | `GET https://www.bienici.com/suggest.json?q=<place>` | Resolve a place name / postal code (e.g. `Paris`, `Paris 15e`, `69000`) to Bien'ici `zoneIds` |
| Listings | `GET https://www.bienici.com/realEstateAds.json?filters=<url-encoded JSON>` | Paginated search results with every field needed |

The `filters` parameter is a URL-encoded JSON object:

```json
{
  "size": 60, "from": 0, "page": 1, "resultsPerPage": 60,
  "filterType": "buy", "propertyType": ["flat"],
  "sortBy": "publicationDate", "sortOrder": "desc",
  "onTheMarket": [true],
  "zoneIdsByTypes": { "zoneIds": ["-7444"] },
  "minPrice": 200000, "maxPrice": 600000, "minRooms": 2
}
```

Because the data is already structured JSON, the actor uses Crawlee's **`HttpCrawler`** (plain HTTP, no browser and no HTML parsing). No Playwright or Puppeteer is required, so it is cheap to run and can execute from datacenter IPs.

### Build A French Property Database Without A Bien'ici API

Bien'ici does not document an open or public API; only its internal JSON endpoints (geo-suggest plus `realEstateAds.json`) are used here. The reverse-engineering order followed was: embedded JSON blobs (none present) then third-party search backend (none found) then the internal/mobile JSON API (used here) then static HTML then a browser. The internal JSON API is both the cheapest and the most complete surface.

**Known limitations**

- New-build ("programme") ads frequently omit DPE/GES and bedroom counts, so those fields come back `null` for such listings.
- Bien'ici caps how deep pagination can go for very large result sets; the actor requests `maxAuthorizedResults` accordingly and stops cleanly.
- Residential Apify proxies are **not required** (the JSON API is not bot-walled), but the standard proxy input is available if you want to spread requests.

### Input Parameters

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `startUrls` | array (requestListSources) | No | `https://www.bienici.com/recherche/achat/paris-75000` | Bien'ici search-result URLs, e.g. `.../recherche/achat/paris-75000` or `.../recherche/location/lyon-69000`. Transaction and location are read from each link. |
| `locations` | array (stringList) | No | - | French place names to search, e.g. `Paris`, `Paris 15e`, `Lyon`, `69000`, `Bordeaux`. Each is resolved to a Bien'ici zone via geo-suggest. |
| `transaction` | string (enum) | No | `buy` | `buy` (achat) or `rent` (location). Only used for entries in `locations` (search URLs define their own transaction). |
| `propertyTypes` | array (stringList) | No | all | Leave empty for all types. Allowed: `flat`, `house`, `terrain`, `parking`, `building`, `loft`, `castle`, `townhouse`, `premises`, `shop`, `office`, `others`. |
| `minPrice` | integer | No | - | Minimum price in euros. |
| `maxPrice` | integer | No | - | Maximum price in euros. |
| `minArea` | integer | No | - | Minimum living surface in square metres. |
| `maxArea` | integer | No | - | Maximum living surface in square metres. |
| `minRooms` | integer | No | - | Minimum number of rooms. |
| `maxRooms` | integer | No | - | Maximum number of rooms. |
| `minBedrooms` | integer | No | - | Minimum number of bedrooms. |
| `maxBedrooms` | integer | No | - | Maximum number of bedrooms. |
| `maxItems` | integer | No | `300` | Maximum listings to return across all searches. Free users are capped at 10. |
| `maxPages` | integer | No | `5` | Maximum result pages (60 listings each) per search task. Hard-capped at 50. |
| `maxConcurrency` | integer | No | `3` | Maximum number of parallel requests. |
| `proxy` | object (proxy) | No | `useApifyProxy: false` | Standard Apify proxy picker. Off by default; available if you want to spread requests. |

### Output Fields

One dataset item per listing. The default `overview` view shows Title, Price, €/m², Surface, Rooms, Bedrooms, DPE, GES, City, Postal code, Agency and URL.

| Field | Type | Description |
|---|---|---|
| `id` | string | Bien'ici listing id. |
| `url` | string | Direct bienici.com listing URL. |
| `title` | string | Listing title. |
| `description` | string | Full ad text. |
| `price` | number | Asking price in euros. |
| `priceWithoutFees` | number | Price excluding fees. |
| `pricePerSquareMeter` | number | Price per m². |
| `surfaceArea` | number | Living surface (m²). |
| `roomsQuantity` | number | Number of rooms. |
| `bedroomsQuantity` | number | Number of bedrooms. |
| `bathroomsQuantity` | number | Number of bathrooms. |
| `energyClass` | string | DPE class (A-G). |
| `gesClass` | string | GES class (A-G). |
| `energyValue` | number | Raw DPE value. |
| `gesValue` | number | Raw GES value. |
| `city` | string | City. |
| `postalCode` | string | Postal code. |
| `district` | string | District / quartier. |
| `departmentCode` | string | Department code. |
| `latitude` | number | GPS latitude. |
| `longitude` | number | GPS longitude. |
| `agencyName` | string | Agency / broker name. |
| `accountType` | string | Advertiser account type. |
| `agencyId` | string | Agency id. |
| `adType` | string | Transaction type (buy/rent). |
| `propertyType` | string | Property type. |
| `reference` | string | Advertiser reference. |
| `photoCount` | integer | Number of photos. |
| `photos` | array | Photo URLs (full list). |
| `virtualTours` | array | Virtual-tour URLs. |
| `with360` | boolean | Whether the listing has 360°/3D media. |
| `isNew` | boolean | New-build listing flag. |
| `isExclusive` | boolean | Exclusive listing flag. |
| `isPro` | boolean | Professional (agency) listing flag. |
| `hasTerrace` | boolean | Terrace flag. |
| `hasBalcony` | boolean | Balcony flag. |
| `hasCellar` | boolean | Cellar flag. |
| `floor` | number | Floor number. |
| `floorQuantity` | number | Number of floors. |
| `heating` | string | Heating type. |
| `feesChargedTo` | string | Who pays the fees. |
| `isInCondominium` | boolean | Condominium flag. |
| `annualCondominiumFees` | number | Annual condominium fees. |
| `priceHasDecreased` | boolean | Whether the price has dropped. |
| `publicationDate` | string | Publication date. |
| `modificationDate` | string | Last modification date. |
| `searchTask` | string | Search that produced the row. |
| `scrapedAt` | string | ISO timestamp of extraction. |

### Example Input And Output

**Input**

```json
{
  "locations": ["Paris 15e"],
  "transaction": "buy",
  "propertyTypes": ["flat"],
  "minRooms": 3,
  "maxPrice": 900000,
  "maxItems": 200,
  "maxPages": 5
}
```

**Output (one dataset row)**

```json
{
  "id": "abc123def456",
  "url": "https://www.bienici.com/annonce/vente/paris-15e/appartement-3pieces-abc123def456",
  "title": "Appartement 3 pièces 68 m² Paris 15e",
  "description": "Bel appartement lumineux au 4e étage ...",
  "price": 795000,
  "priceWithoutFees": 780000,
  "pricePerSquareMeter": 11691,
  "surfaceArea": 68,
  "roomsQuantity": 3,
  "bedroomsQuantity": 2,
  "bathroomsQuantity": 1,
  "energyClass": "D",
  "gesClass": "D",
  "energyValue": 198,
  "gesValue": 34,
  "city": "Paris",
  "postalCode": "75015",
  "district": "Necker",
  "departmentCode": "75",
  "latitude": 48.84123,
  "longitude": 2.30112,
  "agencyName": "Agence Exemple",
  "accountType": "pro",
  "agencyId": "agency-99",
  "adType": "buy",
  "propertyType": "flat",
  "reference": "REF-12345",
  "photoCount": 12,
  "photos": ["https://.../photo1.jpg"],
  "virtualTours": [],
  "with360": false,
  "isNew": false,
  "isExclusive": false,
  "isPro": true,
  "hasTerrace": true,
  "hasBalcony": false,
  "hasCellar": true,
  "floor": 4,
  "floorQuantity": 6,
  "heating": "individuel",
  "feesChargedTo": "buyer",
  "isInCondominium": true,
  "annualCondominiumFees": 1800,
  "priceHasDecreased": true,
  "publicationDate": "2026-09-02",
  "modificationDate": "2026-10-01",
  "searchTask": "buy:Paris 15e",
  "scrapedAt": "2026-10-11T09:00:00.000Z"
}
```

### Integrations & Automation

Every Apify actor is reachable through the **Apify API**, and this one plugs into **webhooks**, **Zapier** and **Make** so results can flow into a Google Sheet, Airtable base, CRM or data warehouse. For market research and price monitoring, run it on a **schedule**: a daily or weekly snapshot of your target cities is enough to track new listings, price changes and DPE distributions, and recurring runs also improve the actor's Store recommendation signals.

### Related Actors

- [bienici-scraper-ppr](https://apify.com/silentflow/bienici-scraper-ppr): a Bien'ici scraper, the largest actor in the topic cluster.
- [bienici-property-search-scraper](https://apify.com/stealth_mode/bienici-property-search-scraper): another Bien'ici property-search actor.
- [housinganywhere-scraper](https://apify.com/ahmed_jasarevic/housinganywhere-scraper): European rental listings to complement Bien'ici's for-sale inventory.
- [savills-scraper](https://apify.com/ahmed_jasarevic/savills-scraper): international real-estate listings for a wider property dataset.
- [century21-scraper](https://apify.com/ahmed_jasarevic/century21-scraper): global real-estate listings, another source for a multi-portal property database.

### FAQ

#### Existe-t-il une API Bien'ici ?

No open or public API is documented. Bien'ici is a client-side SPA whose listings are loaded from internal JSON endpoints (`suggest.json` for geo resolution and `realEstateAds.json` for listings). This actor calls those same endpoints, so you get structured French listings without an API key and without a browser.

#### What are the alternatives to this actor / this data source?

For French property data you can combine this with SeLoger, PAP, Logic-Immo or Leboncoin scrapers. Bien'ici is backed by the FNAIM network and is one of the largest French portals, so it is worth having alongside the others to widen coverage of buy and rent listings and DPE data.

#### How do I get French property listings with DPE/GES and price per m²?

Provide `locations` (e.g. `Paris 15e`) or `startUrls`, set `transaction` to `buy` or `rent`, and add any price/surface/room filters. The actor resolves each place to a Bien'ici zone and returns one row per listing with `pricePerSquareMeter`, `energyClass`, `gesClass`, `surfaceArea`, `roomsQuantity` and coordinates.

#### Why are DPE, GES or bedroom counts null on some rows?

New-build ("programme") ads frequently omit energy classes and bedroom counts on Bien'ici, so those fields come back `null` for such listings. This is expected and not a scrape failure.

#### Do I need a proxy or a browser?

Neither is required. The internal JSON API is not Cloudflare-walled, so the actor runs on plain HTTP from datacenter IPs. The proxy input is available if you want to spread requests across IPs.

#### How deep can a run paginate?

Bien'ici caps how deep pagination can go for very large result sets. The actor requests `maxAuthorizedResults` accordingly and stops cleanly; `maxPages` (default 5, hard cap 50) bounds each search and `maxItems` (default 300) bounds the total.

### SEO Keywords

bienici, bien ici, annonces immobilieres, scraper immobilier, donnees immobilieres, prix immobilier, dpe, marche immobilier, api immobilier, estimation immobiliere, prix m2 immobilier, achat immobilier, location appartement, base de donnees immobiliere, agences immobilieres france, bienici api, bienici alternative, immobilier france, annonces immobilieres france, prix immobilier france

### For AI Agents & LLM Apps

Purpose: return one structured French property-listing row per Bien'ici ad for a given set of locations or search URLs and transaction type.

Minimal working input:

```json
{ "locations": ["Paris 15e"], "transaction": "buy", "maxItems": 60 }
```

Variant input (scrape explicit search URLs):

```json
{ "startUrls": [{ "url": "https://www.bienici.com/recherche/location/lyon-69000" }], "maxItems": 60 }
```

Output fields: `id, url, title, description, price, priceWithoutFees, pricePerSquareMeter, surfaceArea, roomsQuantity, bedroomsQuantity, bathroomsQuantity, energyClass, gesClass, energyValue, gesValue, city, postalCode, district, departmentCode, latitude, longitude, agencyName, accountType, agencyId, adType, propertyType, reference, photoCount, photos, virtualTours, with360, isNew, isExclusive, isPro, hasTerrace, hasBalcony, hasCellar, floor, floorQuantity, heating, feesChargedTo, isInCondominium, annualCondominiumFees, priceHasDecreased, publicationDate, modificationDate, searchTask, scrapedAt`.

Behaviors an agent should know:

- Two discovery modes: `locations` (French place names resolved via geo-suggest, using `transaction`) or `startUrls` (search URLs that carry their own transaction and location).
- `transaction` applies only to `locations` entries; `buy` is the default.
- `maxItems` defaults to **300**; free-plan runs are capped at **10** listings.
- `maxPages` defaults to **5** (60 listings per page) and is hard-capped at 50.
- `energyClass`/`gesClass` and `bedroomsQuantity` can be `null` for new-build listings; do not treat that as a failure.
- No browser or proxy is required; plain HTTP `HttpCrawler` is used.

Billing: pay-per-event: **$0.001 per result** ($1.00 / 1,000 listings) plus a $0.00005 actor-start event.

### Legal & Compliance Disclaimer

This actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by Bien'ici or the FNAIM network**. It accesses only publicly available Bien'ici listing data through the site's own internal JSON endpoints; it does not log in, bypass authentication, or solve CAPTCHAs on anyone's behalf. Users are responsible for ensuring their use complies with Bien'ici's Terms of Service and with applicable data-protection law (including the GDPR, since the data concerns French/EU listings). Where output includes agency contact details, it must not be used for unsolicited commercial outreach in violation of applicable law.

# Actor input Schema

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

Bien'ici search result URLs (e.g. https://www.bienici.com/recherche/achat/paris-75000 or .../recherche/location/lyon-69000). Transaction and location are read from each link.

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

French place names to search (e.g. Paris, Paris 15e, Lyon, 69000, Bordeaux). Each is resolved to a Bien'ici zone via geo-suggest.

## `transaction` (type: `string`):

Buy or rent. Only used for entries in 'Locations' (search URLs define their own transaction).

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

Leave empty for all types. Allowed values: flat, house, terrain, parking, building, loft, castle, townhouse, premises, shop, office, others.

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

Minimum price in euros.

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

Maximum price in euros.

## `minArea` (type: `integer`):

Minimum living surface in square metres.

## `maxArea` (type: `integer`):

Maximum living surface in square metres.

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

Minimum number of rooms.

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

Maximum number of rooms.

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

Minimum number of bedrooms.

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

Maximum number of bedrooms.

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

Maximum number of listings to return across all searches. Free users are capped at 10.

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

Maximum number of result pages (60 listings each) per search task. Hard-capped at 50.

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

Maximum number of parallel requests.

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

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.bienici.com/recherche/achat/paris-75000"
    }
  ],
  "transaction": "buy",
  "maxItems": 300,
  "maxPages": 5,
  "maxConcurrency": 3,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# 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.bienici.com/recherche/achat/paris-75000"
        }
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/bienici-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.bienici.com/recherche/achat/paris-75000" }],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/bienici-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.bienici.com/recherche/achat/paris-75000"
    }
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/bienici-scraper --silent --output-dataset

```

## MCP server setup

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