999.md API: anunțurile din Moldova în JSON
Pe 999.md lumea din Moldova vinde, cumpără și dă în chirie de toate: apartamente în Botanica sau Ciocana, mașini, telefoane, tehnică agricolă. Acest API face două lucruri: caută după text în anunțurile publice și citește un anunț întreg după numărul lui. Prețul rămâne așa cum l-a scris autorul, în lei moldovenești, euro sau dolari, fără nicio conversie, iar anunțul complet aduce și caracteristicile din formular: tipul ofertei, numărul de camere, suprafața, etajul, regiunea și localitatea. Nu are legătură cu contul de vânzător sau cu publicarea pe 999.md: nu postează, nu ridică anunțuri și nu citește mesaje, ci doar ce vede oricine deschide site-ul fără cont.
Endpointuri
| endpoint | Ce returnează | Obligatorii |
|---|---|---|
| search | Căutare după text în anunțurile publice (1–40 de caractere); rezultatele vin în română. Pe fiecare rând: id-ul anunțului, adresa, titlul, prețul și moneda, câmpurile de preț ale sursei (`price_mode`, `bargain`, `down_payment`) și fotografiile. Cel mult 20 de rânduri pe pagină (`limit`, implicit 10) și doar paginile 1 și 2. | query |
| listing_detail | Un singur anunț, cerut prin id-ul primit la căutare sau prin adresa https://999.md/ro/<id>: titlu, preț, descrierea autorului, toate fotografiile, starea anunțului și caracteristicile din formular cu valorile lor, inclusiv „Tipul ofertei”, „Regiune” și „Localitate”. | listing_id |
Fiecare apel se taxează în credite. Apelurile eșuate și blocate sunt gratuite.
Exemplu funcțional
Căutarea a găsit 102 anunțuri; pe prima pagină de 20, patru aveau prețul în lei (MDL), restul în euro. În căutare, primele două rânduri arată la fel (900 MDL și 450 EUR, ambele preț fix), dar apartamentul de 900 de lei se închiriază pe zi: asta se vede doar în `listing_detail`, la „Tipul ofertei”: „De închiriat pe zi”. Dacă faci media chiriilor din Botanica numai din rândurile de căutare, iei la grămadă tarife pe zi și tarife lunare, în lei și în euro. Prima fotografie are în adresă un `?metadata=`: așa publică acum 999.md o parte din imagini, iar adresa e păstrată întocmai.
curl -X POST https://api.reefapi.com/999-md/v1/search \
-H "x-api-key: CHEIA_TA_API" \
-H "content-type: application/json" \
-d '{"query": "chirie apartament botanica", "limit": 20}'{
"ok": true,
"data": {
"query": "chirie apartament botanica",
"page": 1,
"limit": 20,
"count": 20,
"results": [
{
"listing_id": "85621258",
"url": "https://999.md/ro/85621258",
"title": "Apartament cu 1 cameră, 27 m², 9 etaj",
"price": 900,
"currency": "MDL",
"source_price": 900,
"price_mode": "PM_FIXED",
"price_unit": "UNIT_MDL",
"bargain": false,
"down_payment": 0,
"is_expired": false,
"images": [
"https://i.simpalsmedia.com/999.md/BoardImages/900x900/9fdb831261f4fb4ac2f3bcc4469d4e1d.jpg?metadata=%7B%22metadata_version%22%3A+1%2C+%22width%22%3A+1200%2C+%22height%22%3A+900%2C+...%7D",
...
],
"gtin": null
},
{
"listing_id": "105452605",
"url": "https://999.md/ro/105452605",
"title": "Apartament cu 1 cameră, 37 m², 2 etaj",
"price": 450,
"currency": "EUR",
"price_mode": "PM_FIXED",
"price_unit": "UNIT_EUR",
...
},
...
],
"source_total": 102,
"source_has_more": true,
"has_more": true,
"coverage": "Moldova native full-text search, Romanian presentation; pages 1-2."
}
}Ce întâlnește un scraper scris de mână pentru 999.md
Pagina de rezultate nu are anunțurile în HTML. Adresa de căutare pe care o publică site-ul (/ro/search?query=…) întoarce doar scheletul aplicației, iar rezultatele le încarcă după aceea pagina însăși. Un parser de HTML vede o pagină fără niciun anunț și n-are de unde ști că nu e un rezultat gol.
Fotografiile nu sunt toate în datele structurate ale paginii: la anunțurile de mașini pe care le-am verificat, blocul Product JSON-LD avea doar primele cinci imagini, deși anunțul avea mai multe. Lista completă o luăm din datele anunțului, nu din JSON-LD.
Iar formatul se schimbă fără niciun aviz. Pe 25 octombrie 2026 am reparat exact o asemenea schimbare: 999.md începuse să adauge la numele unor fotografii un `?metadata=` cu JSON codificat, iar verificarea noastră accepta doar nume terminate în .jpg, .jpeg, .png sau .webp. Un singur rând de felul ăsta făcea toată căutarea să cadă cu SCHEMA_DRIFT: 23 din 30 de apeluri, pe 10 interogări reale. După corectură, cinci căutări (chirie, tractor, canapea, dacia logan, apartament) au mers 5 din 5, cu câte 20 de rânduri.
Un script făcut în casă trece prin primele două fără să se plângă: raportează zero anunțuri sau păstrează doar cinci poze. La a treia, fie se împiedică de primul nume de fișier pe care nu-l recunoaște, fie îl salvează fără să observe. Dacă urmărești zilnic prețurile la apartamente sau la mașini, verificarea datelor trebuie să ruleze la fel de des ca scriptul.
Limite și note oneste
- API-ul nu e făcut și nici aprobat de 999.md, iar între noi și administratorii site-ului nu există vreo înțelegere.
- Căutarea primește doar text: nu poți alege categoria, regiunea sau intervalul de preț și nici ordinea rezultatelor. Pagina 3 și cele de după sunt respinse (`INVALID_PARAM`, verificat pe 26 octombrie), deci o căutare dă cel mult 40 de anunțuri, chiar dacă `source_total` arată mai multe (102 în exemplul de mai sus, 22 042 la „apartament chisinau”).
- Rândurile din căutare nu au regiunea, localitatea și tipul ofertei; le găsești în `listing_detail`, printre `attributes`. Tot acolo afli că un anunț e de cumpărare: la „iphone 15”, primul rezultat era „Cumpăr iPhone-ul tău !”, cu „Tipul ofertei”: „Cumpăr”.
- Moneda e cea aleasă de autor (MDL, EUR sau USD) și nu convertim nimic. `price` e completat doar pentru prețuri fixe (`PM_FIXED`) într-o monedă recunoscută; altfel e `null`, iar câmpurile originale rămân în răspuns.
- Caracteristicile de tip da/nu sunt bifele din formularul anunțului și pot contrazice descrierea: la anunțul 105581090 descrierea spune „mobilat și utilat”, iar „Mobilat” vine `false`.
- Telefonul, e-mailul și adresa exactă nu sunt returnate ca atare. Descrierea vine însă exact cum a scris-o autorul, deci poate conține date de contact puse de el în text.
- Valoarea e cea pe care o cere autorul; la cât s-a vândut sau s-a închiriat până la urmă nu se vede nicăieri pe site. GTIN nu există în datele anunțurilor (`gtin` e mereu `null`), iar interfața în rusă a site-ului nu e acoperită.
- Fiecare apel costă 1 credit, fie căutare, fie anunț complet.