API

Storia.ro API: anunțuri imobiliare din România în JSON

Motorul se numește `otodom` pentru că storia.ro rulează pe aceeași platformă ca otodom.pl. Pentru România trimite `site: "ro"`; dacă lipsește, se caută pe otodom.pl și prețurile vin în zloți. Citim anunțurile așa cum le vede oricine caută o locuință pe Storia (preț, preț pe m², suprafață, camere, etaj, sector și cartier, persoană fizică sau firmă) și le întoarcem în JSON. Nu este o unealtă pentru agenții: nu publică anunțuri și n-are legătură cu pachetele sau tarifele de promovare Storia.

Endpointuri

endpointCe returneazăObligatorii
searchAnunțuri de vânzare sau de închiriere după tipul proprietății și localitate (id-ul din `locations`), cu filtrele site-ului: preț, preț pe m², suprafață, număr de camere, etaj, anul construcției, ofertant (persoană fizică, agenție, dezvoltator), piață primară sau secundară, cuvânt din descriere și dotări. Opțiunile de sortare sunt cele ale site-ului.toate opționale
listingAnunțul complet după `listing_id` (codul ID… de la finalul adresei) sau după URL: preț, preț pe m², garanție la chirie, suprafață, etaj, anul construcției, material, încălzire, stadiul construcției, descriere, fotografii, coordonate și tipul ofertantului. Pentru un ansamblu rezidențial: prețul „de la” pe m² și primele unități.toate opționale
locationsCăutarea de localități: scrii „Bucuresti” sau „Cluj” și primești id-urile folosite de Storia, cu nivelul lor (județ, sector, cartier). Diacriticele nu sunt obligatorii.query

Fiecare apel se taxează în credite. Apelurile eșuate și blocate sunt gratuite.

Exemplu funcțional

Prețurile sunt cele cerute în anunț, nu prețuri de tranzacție. La București `location.city` vine `null` (în căutarea noastră, 36 din 36 de rânduri): sectorul și cartierul stau în `levels` și în `full_name`, deci o medie pe m² pe cartier se calculează după `location_id`. `decoy_rows_dropped: 1` înseamnă că am scos de pe pagină un rând fals pe care l-a inserat chiar site-ul.

Cerere
curl -X POST https://api.reefapi.com/otodom/v1/search \
  -H "x-api-key: CHEIA_TA" \
  -H "content-type: application/json" \
  -d '{"site": "ro", "transaction": "sell", "estate": "flat", "location": "bucuresti/sectorul-3", "rooms": ["2"]}'
Răspuns (prescurtat)
{
  "ok": true,
  "data": {
    "results": [
      ...
      {
        "listing_id": "IDISY9",
        "kind": "ad",
        "title": "Apartament Decomandat 2 camere - Th. Pallady Metrou N. Teclu",
        "price": 112999,
        "currency": "EUR",
        "price_type": "sale_price",
        "price_per_m2": 1782.88,
        "maintenance_fee_monthly": null,
        "area_m2": 63.38,
        "rooms": 2,
        "floor_number": 2,
        "location": {
          "region": "Bucuresti",
          "city": null,
          "district": "Theodor Pallady",
          "location_id": "bucuresti/sectorul-3/theodor-pallady",
          "full_name": "Theodor Pallady, Sectorul 3, Bucuresti"
        },
        "advertiser_type": "business",
        "tags": ["SEPARATE_KITCHEN", "BALCONY"]
      },
      {
        "listing_id": "IDIZYa",
        "kind": "ad",
        "title": "2 Camere de vanzare | Dristor | Metrou | Reabilitat|Necesita Renovare",
        "price": 130000,
        "currency": "EUR",
        "price_type": "sale_price",
        "price_per_m2": 2549.02,
        "area_m2": 51,
        "rooms": 2,
        "floor_number": 1,
        "location": {
          "region": "Bucuresti",
          "city": null,
          "district": "Dristor",
          "location_id": "bucuresti/sectorul-3/dristor",
          "full_name": "Dristor, Sectorul 3, Bucuresti"
        },
        "advertiser_type": "business"
      },
      ...
    ],
    "total": 2784,
    "last_page": 78,
    "has_more": true,
    "decoy_rows_dropped": 1
  },
  "meta": { "record_count": 36, "cache_hit": false, "mode": "live" }
}

Ce găsește un scraper propriu pe storia.ro

Paginarea nu se termină cu o pagină goală. Dacă ceri o pagină de după ultima, site-ul te redirecționează la ultima pagină și o servește din nou, cu tot cu anunțuri. O buclă de tipul „crește `page` până nu mai vin anunțuri” nu se oprește singură și adună aceleași 36 de anunțuri iar și iar. La verificarea noastră, pentru 2 camere în Sectorul 3 erau 78 de pagini, iar pagina 200 ar fi fost tot pagina 78. Prin API primești în acest caz 0 rânduri, `page_clamped: true` și `last_page`.

Moneda nu e aceeași pe tot site-ul: storia.ro acceptă anunțuri atât în euro, cât și în lei, iar moneda se citește din fiecare rând. Un script care presupune euro peste tot (sau lei) amestecă cele două fără să dea vreo eroare.

Mai există și un anunț-capcană: pe aproape fiecare pagină de rezultate site-ul strecoară un rând cu data adăugării 29 februarie 1999, care poate copia titlul și prețul unui anunț real de lângă el. În ambele căutări pe care le-am făcut a apărut câte o dată și a fost eliminat.

Fiecare dintre cele trei strică altfel o medie a prețului pe m² pe cartier: paginile servite din nou dublează anunțuri, moneda presupusă amestecă euro cu lei, iar rândul fals mai numără o dată un preț real. Niciuna nu produce o eroare, așa că se descoperă de obicei abia când cifrele nu mai par plauzibile.

Limite și note oneste

  • Serviciul nu e oferit și nici susținut de Storia: nu este o interfață oficială a portalului și nu avem un parteneriat cu Storia.
  • Fără `site: "ro"`, cererea ajunge pe otodom.pl. Id-urile de localitate din România (de exemplu `bucuresti/sectorul-3`) vin din `locations` cu același `site`.
  • Primești prețul cerut. Prețuri de tranzacție și istoric de preț nu există în răspuns.
  • Întreținerea lunară (`maintenance_fee_monthly`) apare doar dacă ofertantul a completat-o: 0 din 36 de rânduri la vânzare în Sectorul 3 și 13 din 36 la închirieri în București, în măsurătorile noastre.
  • Numărul de camere este cel completat în anunț. În aceeași căutare, două anunțuri cu „Studio” în titlu au venit cu `rooms: 2`.
  • În cele 72 de rânduri măsurate (vânzare și închiriere, București) toate prețurile erau în EUR; asta nu garantează că nu apar și anunțuri în RON.
  • Nu există căutare pe rază în jurul unui punct și nici pe mai multe localități în aceeași cerere.
  • Răspunsurile nu se păstrează în cache: fiecare cerere citește storia.ro în acel moment.