# akelius — Akelius Residential (Grand Montréal) - site: https://rent.akelius.com/en/search/canada/apartment/montreal - méthode: json-api (TransferState Angular SSR + JSON détail /lettings/marketing/v2/CA/<id>.json) - annonces: 247 → 247 - couverture après (sur 247 annonces): prix 100%, adresse 100%, dispo 100%, superficie 100%, commodités 100% - fixture: ok · test: ok (2 passed) ## Champs extraits - **Carte liste (TransferState de la page de recherche)** : id, adresse (rue, ville, code postal, borough), lat/lng, loyer (`total-rent`), disponibilité (`is-available-from-now-on` / `available-from-date`), superficie (`unit-size`), chambres/sdb, étage, type (loft/apartment), promotion (`free-rent`), photos 400 px. - **JSON détail** (`/lettings/marketing/v2/CA/.json`, via `self.detail()` avec clé = sha1(loyer, dispo, lastPublishedDate), max 150 nouveaux fetchs/sync) : - `pets` structuré (`pets-allowed`: yes/no → oui/non, autre → conditions) ; - `furnished` structuré (`furnished-state`) ; - `details.inclusions{heating, electricity, hot_water, internet}` (booléens explicites) ; - `details.appliances{dishwasher, washer_dryer}` ; - `details.ac / elevator / balcony / pool / gym / laundry / construction_year / contact.phone` ; - ~30 commodités keyfacts booléennes → libellés français dans `amenities` (climatisation, ascenseur, balcon, buanderie, piscine, chauffage/eau chaude inclus, etc.) ; - photos 600 px (remplacent les 400 px de la liste) ; - description libre (`free-text`) si présente. ## Champs indisponibles à la source - Pas de description marketing rédigée par unité (le keyfact `free-text` est rarement rempli). - Pas d'info stationnement dans les keyfacts canadiens (ni type ni prix). - Pas de politique fumeur. - `pets-allowed` absent sur ~10 % des unités (26/247) — laissé à None. ## Fragilités - Le TransferState est encodé avec `&q;` au lieu de `"` et la clé du cache API est un hash variable : on repère la liste d'unités par heuristique (`keyfacts` dans le premier élément). - Le JSON détail est servi depuis un blob Azure avec BOM UTF-8 : décodage `utf-8-sig` obligatoire (`resp.json()` échouerait). - Le chemin `/lettings/marketing/v2/CA/…` est déduit du bundle JS (non documenté) — surveiller un éventuel changement de version (v2 → v3). - 259 unités QC dans le flux : la première synchronisation ne visite que 150 détails (budget), la deuxième complète le reste ; ensuite le cache BD évite tout refetch tant que loyer/dispo/lastPublishedDate ne bougent pas. - Toronto/Ottawa dans le même flux : le filtre province+ville doit rester à jour si Akelius ajoute des villes QC. ## Améliorations apportées - Découverte et intégration du JSON détail par unité (endpoint non documenté trouvé dans le bundle Angular). - Nouveaux champs : `pets`, `furnished`, `details` structurés (inclusions, électroménagers, ac, ascenseur, balcon, piscine, gym, buanderie, année de construction, téléphone de contact). - Commodités passées de 2 items génériques (« X pi² », « N sdb ») à la liste réelle des keyfacts vrais, en français. - Photos upgradées de 400 px à 600 px depuis `documents[]`. - Visites détail plafonnées (150/sync) et mises en cache via `self.detail()` (clé dérivée du contenu liste). ## Échantillon avant/après **4557 Sherbrooke Street West — unité 12** (1795 $, 3½, dispo 2026-10-01, 553 pi²) - avant : pets=None, details=`{}`, amenities=["553 pi²","1 sdb"] - après : pets=`oui`, details=`{"inclusions": {"heating": true, "hot_water": true, "electricity": false, "internet": false}, "appliances": {"washer_dryer": true, "dishwasher": false}, "laundry": true, "ac": false, "elevator": false, …, "construction_year": 1920, "contact": {"phone": "+1 438 998 0689"}}` **4557 Sherbrooke Street West — unité 304** (3095 $, 5½, dispo 2026-10-01, 1012 pi²) - avant : pets=None, details=`{"floor": 3}` - après : pets=`oui`, details=`{"inclusions": {"heating": true, "hot_water": true, "electricity": false, "internet": false}, "appliances": {"dishwasher": true, "washer_dryer": true}, "ac": true, "laundry": true, "floor": 3, "elevator": …}`