# DPE Distress Leads — French F/G Energy-Sieve Property Feed (`studio-amba/dpe-distress-leads`) Actor

Find DPE F and G property listings (passoires thermiques) in France. Runs Bien'ici and LeBonCoin, keeps only energy-sieve listings, attaches a Loi Climat rental-ban urgency flag (G banned since 2025, F from 2028), dedupes across portals, and flags private-owner vs agency.

- **URL**: https://apify.com/studio-amba/dpe-distress-leads.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result scrapeds

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/platform/actors/running/actors-in-store#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

## DPE Distress Leads — French F/G Energy-Sieve Property Feed

Find **DPE F and G property listings** ("passoires thermiques" — energy sieves) across the main French real-estate portals in one run. DPE Distress Leads runs Bien'ici and LeBonCoin (SeLoger and Logic-Immo optional), keeps only the worst-rated listings, attaches a **Loi Climat rental-ban urgency flag**, deduplicates the same property across portals, and flags each result as sold by a **private owner** or by an **agency**.

These are motivated, time-pressured sellers: the French rental-ban timeline is already forcing owners of energy sieves to sell or renovate.

### Why F and G listings are distress leads

France's Loi Climat et Résilience bans the rental of the worst energy grades on a fixed timeline:

- **G — banned since 1 January 2025** (already illegal to rent out)
- **F — banned from 1 January 2028**
- **E — banned from 1 January 2034**

An owner of an F or G property that they can no longer legally rent faces a choice: an expensive renovation, or sell. That makes an F/G listing a distress signal, and an **F/G sold directly by its owner (FSBO)** the premium lead — urgent, motivated, and reachable without an agency mandate.

### What it does

- **DPE F/G filter.** Every returned row is a listing rated in your chosen grades (default F and G). Listings without a rating (NS / vierge / absent) are excluded by design — a distress lead has to be confirmed.
- **Rental-ban urgency flag.** Each row carries `dpeUrgency` mapping its grade to the Loi Climat ban date.
- **Cross-portal dedup.** The same property on more than one portal is merged into one row using a content fingerprint (postcode + property type + surface, then price proximity). No shared listing ID exists between French portals.
- **FSBO vs agency classification.** LeBonCoin exposes an explicit private-vs-professional seller flag; agency listings carry an agency name. Every row is labelled `particulier`, `professionnel`, or `unknown`.
- **New-listing delta.** Turn on "only new since last run" and each run returns only distress properties not seen before, backed by a per-account store.
- **Optional agency enrichment.** Cross-reference agency-listed properties against PagesJaunes to attach agency phone and SIRET.

### How to scrape French DPE F/G property data

1. Enter a **location** — a city or department (`Paris`, `Lyon`, `Bordeaux`, `Gironde`).
2. Keep the default **DPE grades** F and G, or add E for the 2034 horizon.
3. Choose **sale** or **rent** (rental bans make F/G especially urgent for landlords).
4. Pick your **portals**. Bien'ici + LeBonCoin is the reliable, DPE-rich default.
5. Set a **French residential proxy** (recommended — the portals are anti-bot-protected).
6. Optionally set **seller filter** to `FSBO leads only`, or turn on **only new listings**.
7. Run it. Each row is one deduplicated distress property with its DPE grade, ban urgency, FSBO classification, price, surface, price per m², and per-portal source links.

Schedule the actor with "only new since last run" enabled to receive a rolling feed of fresh F/G distress leads for your sector.

### Comment scraper les passoires thermiques (DPE F et G)

DPE Distress Leads récupère automatiquement les **annonces classées DPE F ou G** en France. Il interroge Bien'ici et LeBonCoin (SeLoger et Logic-Immo en option) pour une ville ou un département, ne garde que les passoires thermiques, dédoublonne le même bien présent sur plusieurs portails, et distingue les **annonces de particuliers** des **annonces d'agence**.

- **Urgence loi Climat.** G interdit à la location depuis le 1er janvier 2025, F à partir de 2028, E à partir de 2034. Chaque annonce porte son échéance d'interdiction.
- **Lead premium.** Un bien F ou G vendu par un particulier est un vendeur pressé et joignable sans mandat.
- **Delta des nouvelles annonces.** Activez « uniquement les nouvelles annonces » et planifiez l'acteur pour un flux quotidien de nouvelles passoires thermiques.
- **Enrichissement agences.** Croisement facultatif avec PagesJaunes pour le téléphone et le SIRET de l'agence.

### Portals and reliability (method disclosure)

| Portal | Method | Reliability | DPE coverage |
|---|---|---|---|
| **Bien'ici** | Open JSON API | High | Good — exposes the energy grade on most listings. The default anchor. |
| **LeBonCoin** | Mobile app API | Medium | Grade in the ad attributes when the seller filled it in. DataDome-protected — needs a French residential proxy. |
| **SeLoger** | Browser + API interception | Low | Sparse. Opt-in. |
| **Logic-Immo** | Browser | Low | DataDome-walled; often returns nothing. Opt-in. |

The run degrades gracefully: if a portal fails, the run continues with the others and records which succeeded in the run summary.

### Documented limits

- **DPE coverage is not 100%.** Sellers do not always publish the grade, and some listings show "vierge" or "NS". Those are excluded, so the feed is a high-precision subset, not every F/G property in existence. Bien'ici has the best coverage; raise `maxItemsPerSource` in areas with fewer graded listings.
- **FSBO detection depends on LeBonCoin.** It is the only portal with an explicit private-seller flag. If LeBonCoin is blocked on a run (DataDome), `fsboSourceOk` is set false and the run warns — a low FSBO count then means "source blocked", not "no private sellers".
- **No shared listing ID.** Cross-portal matching is content-based (postcode + type + surface + price), high-precision but not exhaustive.
- **SeLoger / Logic-Immo are opt-in.** They add coverage but currently return sparse or empty rows; excluded from the default for data quality.

### Output fields

Each row is one deduplicated distress property:

- `dpeRating`, `dpeUrgency` — the energy grade and its rental-ban date
- `isFsbo`, `fsboConfidence`, `sellerType` — the FSBO classification
- `isNew`, `firstSeenAt` — the run-over-run delta
- `crossListed`, `portalCount`, `sourcePortals`, `listings[]` — cross-portal presence and per-portal detail
- `priceEur`, `priceMinEur`, `priceMaxEur`, `pricePerM2` — pricing
- `surfaceM2`, `rooms`, `bedrooms`, `propertyType` — the property
- `postalCode`, `city`, `department`, `latitude`, `longitude` — location
- `agencyName`, `agencyPhone`, `agencySiret` — agency detail (phone/SIRET when enrichment is on)
- `sellerName`, `hasPhone` — seller detail

### Example output

```json
{
  "dpeRating": "G",
  "dpeUrgency": "rental_ban_active_2025",
  "isFsbo": true,
  "sellerType": "particulier",
  "isNew": true,
  "propertyType": "apartment",
  "listingTitle": "Appartement 2 pièces 42 m² à rénover",
  "priceEur": 189000,
  "pricePerM2": 4500,
  "surfaceM2": 42,
  "postalCode": "75018",
  "city": "Paris",
  "sellerName": "Marie",
  "hasPhone": true,
  "sourcePortals": ["leboncoin"]
}
```

### Who uses this

- **Renovation and insulation lead-gen** targeting owners forced to act by the ban.
- **Investors** hunting under-priced F/G stock to renovate and relet or resell.
- **Agencies** prospecting distressed owners before a competitor signs the mandate.

### Pricing

Pay per result. You pay for the run start and for each deduplicated distress lead returned. See the pricing tab for current rates.

### FAQ

**Why are some F/G properties missing?**
Only listings that publish a DPE grade are returned. Sellers who omit it, or show "vierge", are excluded so every row is a confirmed distress lead.

**Can I get only the private-seller leads?**
Yes. Set seller filter to `FSBO leads only`. An F/G sold by its owner is the highest-value lead.

**How do I get a feed of only new listings?**
Turn on "only new listings since last run" and schedule the actor.

**Do I need a proxy?**
Yes, a French residential proxy is strongly recommended. The default input is configured for one.

**Is this legal?**
The actor collects publicly listed advertisements. You are responsible for how you use the leads, including French prospection and GDPR rules.

# Actor input Schema

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

French city or department to search, e.g. 'Paris', 'Lyon', 'Bordeaux', 'Gironde'. Drives all selected portals.

## `dpeRatings` (type: `array`):

Which energy grades count as distress. Default F and G (the energy sieves under rental-ban pressure). Add E for the 2034 ban horizon.

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

Sale (ventes) or rent (locations). Rental bans make F/G especially urgent for landlords.

## `propertyType` (type: `string`):

Restrict to one property type. Leave empty for all types.

## `portals` (type: `array`):

Which French portals to run and deduplicate across. Bien'ici and LeBonCoin are the reliable, DPE-rich default (Bien'ici exposes the energy grade on most listings). SeLoger and Logic-Immo are anti-bot-fragile and often return sparse rows; add them for broader coverage.

## `sellerFilter` (type: `string`):

Return all distress listings, only FSBO (private-owner) ones, or only agency-listed. A private owner of an F/G property is the premium lead: urgent and reachable without a mandate.

## `onlyNew` (type: `boolean`):

Return only distress properties not seen in a previous run. Backed by a per-account key-value store. Leave off for a full snapshot.

## `onlyWithContact` (type: `boolean`):

Return only properties where a phone contact is exposed (seller phone or, with agency enrichment, an agency phone).

## `enrichAgencies` (type: `boolean`):

Cross-reference agency-listed properties against PagesJaunes to attach agency phone and SIRET. Adds one extra portal run, so runs take longer. Off by default.

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

Lower price bound passed to the portals that support it. Leave empty for no minimum.

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

Upper price bound passed to the portals that support it. Leave empty for no maximum.

## `maxItemsPerSource` (type: `integer`):

Cap on listings pulled from each portal before the DPE filter and dedup. Raise it in areas with fewer F/G listings.

## `timeoutPerSourceSecs` (type: `integer`):

How long to wait for each portal run before treating it as failed.

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

Passed through to the child portal scrapers. French residential proxy is strongly recommended (LeBonCoin, SeLoger and Logic-Immo are anti-bot-protected).

## Actor input object example

```json
{
  "location": "Bordeaux",
  "dpeRatings": [
    "F",
    "G"
  ],
  "transactionType": "sale",
  "propertyType": "",
  "portals": [
    "bienici",
    "leboncoin"
  ],
  "sellerFilter": "all",
  "onlyNew": false,
  "onlyWithContact": false,
  "enrichAgencies": false,
  "maxItemsPerSource": 40,
  "timeoutPerSourceSecs": 150,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}
```

# 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 = {
    "location": "Paris",
    "dpeRatings": [
        "F",
        "G"
    ],
    "transactionType": "sale",
    "portals": [
        "bienici",
        "leboncoin"
    ],
    "sellerFilter": "all",
    "maxItemsPerSource": 40,
    "timeoutPerSourceSecs": 150,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "FR"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/dpe-distress-leads").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 = {
    "location": "Paris",
    "dpeRatings": [
        "F",
        "G",
    ],
    "transactionType": "sale",
    "portals": [
        "bienici",
        "leboncoin",
    ],
    "sellerFilter": "all",
    "maxItemsPerSource": 40,
    "timeoutPerSourceSecs": 150,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "FR",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/dpe-distress-leads").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "location": "Paris",
  "dpeRatings": [
    "F",
    "G"
  ],
  "transactionType": "sale",
  "portals": [
    "bienici",
    "leboncoin"
  ],
  "sellerFilter": "all",
  "maxItemsPerSource": 40,
  "timeoutPerSourceSecs": 150,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}' |
apify call studio-amba/dpe-distress-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studio-amba/dpe-distress-leads",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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