Skip to main content

Goal

Construire un dataset dédupliqué d’appartements à l’achat sur Paris (puis l’Île-de-France), paginer pour l’exhaustivité, et calculer des statistiques prix au m² par département — sans biais lié aux doublons inter-portails.

Scénario

Vous êtes une fintech ou une équipe analytics qui doit cartographier le marché parisien : stock disponible, médianes prix/m², distribution par dpt. Compter les annonces brutes (Adverts) gonfle le volume car chaque bien est publié sur 3-8 portails. Vous travaillez donc sur Properties (entités dédupliquées) avec pagination cursor et un workflow reproductible.

Étapes

1

1. Choisir Properties (et pas Adverts)

Une Property = 1 bien physique unique = N adverts agrégés. C’est l’objet à utiliser pour tout calcul agrégé : compter des biens (pas des publications), médianes prix, stocks, durées en ligne.Détail de l’asymétrie et des anti-patterns : /concepts/property-vs-advert.
2

2. Construire le payload — combo standard prod

Trois bonnes pratiques :
  • meta.isTotallyOffline: false → exclut les biens dont toutes les adverts sont offline (sinon votre stock contient des fantômes).
  • sortBy: "FIRST_SEEN_AT" + orderBy: "DESC" → vous parcourez du plus récent au plus ancien, idéal pour reprendre une exploration à chaud.
  • meta.firstSeenAt.min → borne temporelle pour ignorer le très ancien (typiquement 2025-01-01T00:00:00.000Z).
  • size: 100 → max autorisé sur l’endpoint full search (lite est plafonné à 25).
3

3. Lire le `searchAfterHash` retourné

La réponse est wrappée sous data et contient items[] (jusqu’à 100 properties), count, et un champ searchAfterHash. C’est un cursor opaque : ne le décodez pas, contentez-vous de le replacer dans la requête suivante.
4

4. Paginer pour exhaustivité (boucle cursor)

Boucle : tant que la dernière page ramène size items, replongez avec searchAfterHash. Stoppez quand len(items) < size (fin du dataset) ou quand votre cap user-defined est atteint.
Deuxième page en curl direct :
5

5. Calculer le prix au m² par département

Une fois le dataset collecté, agrégez par les 2 premiers caractères du postalCode (= département).
6

6. Étendre à toute l'Île-de-France (multi-zones OR)

Pour passer de Paris-1er à Paris + petite couronne, remplacez location[] par 4 zones combinées en OR.
Logique multi-zones complète et autres modes (bbox, geoDistance) : /concepts/recherche-geographique.

Architecture / flow

Pièges fréquents

  • Confondre Properties et Adverts → analytics biaisé : un même bien compté 3-8 fois (1 par portail) gonfle le stock et fausse les médianes. Toujours Properties pour les KPIs marché.
  • Oublier meta.isTotallyOffline: false → vous comptez des biens dont toutes les annonces sont offline (fantômes du catalogue).
  • Tenter une pagination par offset : ça n’existe pas. Le seul mode est cursor searchAfterHash. Ne décodez pas le cursor — c’est opaque.
  • Mixer postalCode et city dans la même entrée : city est ignoré par le moteur. Voir warning city deprecated.
  • Dépasser size max : 100 sur full search, 25 sur lite search. Au-delà, l’API reject ou tronque.
  • Ne pas dédoublonner sur flxId entre pages : un append concurrent peut renvoyer un même item deux fois si le tri change. Conservez un set des flxId vus.

Pour aller plus loin