API

BestPrice.gr API: τιμές, προσφορές και barcode σε JSON

Η λίστα αποτελεσμάτων μιας αναζήτησης ή κατηγορίας, τα καταστήματα που πουλούν ένα προϊόν με τις τιμές τους, η χαμηλότερη και η υψηλότερη τιμή του σε ευρώ: τα δημόσια στοιχεία του bestprice.gr έρχονται εδώ σε JSON, χωρίς εγγραφή στο BestPrice. Αν ο κατάλογός σας έχει barcode, η ενέργεια `barcode` βρίσκει απευθείας το αντίστοιχο προϊόν του BestPrice, εφόσον ο κωδικός υπάρχει στο ευρετήριό του, και γλιτώνετε την αντιστοίχιση με βάση τα ονόματα. Δεν απευθύνεται σε εμπόρους: δεν ανεβάζει XML feed και δεν συνδέεται με λογαριασμό εμπόρου στο BestPrice. Είναι η πλευρά του αγοραστή, όπως φαίνεται τη στιγμή της κλήσης.

Endpoints

endpointΤι επιστρέφειΥποχρεωτικά
searchΑναζήτηση με όρο στα ελληνικά ή στα αγγλικά: τίτλος, η τιμή που δείχνει το BestPrice (δηλαδή η χαμηλότερη) σε ευρώ, σε πόσα καταστήματα υπάρχει και το `product_id`. Όταν το site ανακατευθύνει την αναζήτηση σε σελίδα κατηγορίας ή μάρκας, το `redirected_to` δείχνει ποια. Κάποιες γραμμές είναι αγγελία ενός μόνο καταστήματος (`listing_type: shop_offer`) και δεν έχουν `product_id`.query
categoryΗ λίστα μιας κατηγορίας χωρίς λέξη-κλειδί, με το αριθμητικό id της (π.χ. `806` για τα κινητά) ή το URL της· το προαιρετικό `query` περιορίζει τα αποτελέσματα. Οι γραμμές έχουν την ίδια μορφή με το search.category_id
productΈνα προϊόν με τις προσφορές των καταστημάτων (κατάστημα, τιμή, διαθεσιμότητα), το εύρος τιμών στην αγορά (`price_low_eur`, `price_high_eur`, `offer_count`), τη διαδρομή κατηγορίας και το barcode του (`gtin` μαζί με `gtin_type`).product_id
barcodeΒρίσκει το `product_id` του BestPrice από EAN-13, EAN-8, UPC-12 ή GTIN-14. Κάθε γραμμή έχει `match_type`· από προεπιλογή επιστρέφονται μόνο όσες το ίδιο το BestPrice δηλώνει ως ακριβή αντιστοίχιση (`barcode_exact`).barcode

Κάθε κλήση χρεώνεται σε credits. Οι αποτυχημένες και μπλοκαρισμένες κλήσεις είναι δωρεάν.

Παράδειγμα που δουλεύει

Το BestPrice δεν έκανε αναζήτηση κειμένου: ανακατεύθυνε το ερώτημα στην κατηγορία «Κλιματιστικά με Inverter» (2442), οπότε οι 16 γραμμές είναι η λίστα αυτής της κατηγορίας, όπως δηλώνει το `redirected_to`. Σε κάθε γραμμή το `price_eur` αντιστοιχεί στο φθηνότερο κατάστημα· τις τιμές των υπόλοιπων τις φέρνει το `product` με το ίδιο `product_id`. Για το Toyotomi Umi παρακάτω, το `product` μέτρησε 47 καταστήματα, με τιμές από 417 έως 669 €.

Αίτημα
curl -X POST https://api.reefapi.com/bestprice/v1/search \
  -H "x-api-key: ΤΟ_ΚΛΕΙΔΙ_ΣΑΣ" \
  -H "content-type: application/json" \
  -d '{"query": "κλιματιστικό inverter"}'
Απάντηση (συντομευμένη)
{
  "ok": true,
  "data": {
    "products": [
      {
        "listing_type": "product",
        "product_id": "2159736789",
        "title": "Morris Terra WFIN-35180 Κλιματιστικό Inverter 12000 BTU A+++/A+++ με Ιονιστή και Wi-Fi",
        "price_eur": 223.87,
        "currency": "EUR",
        "category_id": "2442",
        "shop_count": 14
      },
      ...
      {
        "listing_type": "product",
        "product_id": "2159740957",
        "title": "Toyotomi Umi UTN-12CH/UTG-12CH Κλιματιστικό Inverter 12000 BTU A+++/A+++ με Ιονιστή και Wi-Fi",
        "price_eur": 417.0,
        "currency": "EUR",
        "category_id": "2442",
        "shop_count": 47
      },
      ...
    ],
    "page": 1,
    "limit": 24,
    "query": "κλιματιστικό inverter",
    "redirected_to": {
      "type": "category",
      "id": "2442",
      "title": "Κλιματιστικά με Inverter",
      "url": "https://www.bestprice.gr/cat/2442/air-condition/f/71_1/inverter.html"
    }
  },
  "meta": { "record_count": 16, "cache_hit": false, "mode": "live" }
}

Τι θα συναντήσει ένας δικός σας scraper στο BestPrice

Το πρώτο εμπόδιο εμφανίζεται πριν καν φτάσετε στο HTML. Το bestprice.gr κόβει τη σύνδεση ανάλογα με το TLS αποτύπωμα του client: με τα προφίλ Chrome και Firefox που μιμούνται οι βιβλιοθήκες HTTP, η σύνδεση πέφτει από όποιο δίκτυο κι αν δοκιμάσαμε, χωρίς καν σελίδα σφάλματος. Μοιάζει με πεσμένο site ή με μπλοκαρισμένη IP, όμως η αλλαγή IP δεν το λύνει· το κρίσιμο είναι το αποτύπωμα.

Οι τιμές στις κάρτες της λίστας (`data-price` στο HTML) είναι σε λεπτά του ευρώ: 61000 σημαίνει 610,00 €. Αν τις διαβάσετε ως ευρώ, βγαίνουν εκατό φορές μεγαλύτερες. Εδώ έρχονται ήδη σε ευρώ στο `price_eur`· τις συγκρίναμε με την τιμή που εμφανίζεται στην κάρτα και συμφώνησαν 48 στις 48.

Στις μετρήσεις μας το `pg=2` ανακατεύθυνε πίσω στη σελίδα 1, παρότι η σελίδα δηλώνει ότι υπάρχει επόμενη (`rel="next"`). Ένα script που ζητά `pg=2`, `pg=3` μαζεύει ξανά και ξανά τα ίδια 16 προϊόντα. Εδώ κάθε σελίδα μετά την πρώτη επιστρέφει 0 γραμμές και `page_available: false`, ώστε να μη μετρηθούν διπλά.

Τέλος, η αναζήτηση του site δεν βρίσκει barcode: 12 EAN που δημοσιεύει το ίδιο το BestPrice στις σελίδες των προϊόντων του έφεραν 12 φορές «Δεν βρέθηκαν». Γι' αυτό το `barcode` είναι ξεχωριστή ενέργεια.

Όρια και ειλικρινείς σημειώσεις

  • Η υπηρεσία δεν προέρχεται από το BestPrice.gr: δεν είναι επίσημο API του, ούτε συνεργαζόμαστε μαζί του.
  • Επιστρέφεται μόνο η πρώτη σελίδα κάθε λίστας, δηλαδή έως 16 προϊόντα· το `page` πάνω από 1 δεν φέρνει νέα. Για περισσότερα προϊόντα, κάντε την αναζήτηση πιο συγκεκριμένη ή ζητήστε μια πιο στενή κατηγορία.
  • Το `product` φέρνει όσες προσφορές φορτώνει αρχικά η σελίδα του προϊόντος (30 σε κάθε προϊόν που μετρήσαμε, βλ. `offers_listed`), ενώ το `offer_count` μετράει όλη την αγορά: για το ψυγείο LG GBB566PZHMN, 48 καταστήματα και 30 στη λίστα. Το `price_high_eur` (εκεί 1.218,99 €) μπορεί να μην αντιστοιχεί σε καμία γραμμή του `offers[]`· στο ίδιο ψυγείο η ακριβότερη προσφορά της λίστας ήταν 849 €.
  • Το `url` κάθε προσφοράς έρχεται null: σύνδεσμος προς τη σελίδα του καταστήματος δεν επιστρέφεται (60 στις 60 προσφορές σε δύο προϊόντα που ελέγξαμε).
  • Το `barcode` δεν καλύπτει κάθε κωδικό: από 36 barcode που πήραμε από σελίδες του BestPrice βρέθηκαν τα 25. Στα ηλεκτρονικά και στις οικιακές συσκευές βρέθηκαν 3 στα 3, στο σούπερ μάρκετ και στα καλλυντικά 1 στα 3, στην κατηγορία PlayStation 0 στα 3. Κενή απάντηση σημαίνει ότι ο κωδικός δεν υπάρχει στο ευρετήριο barcode του BestPrice, όχι σφάλμα. Τότε μένει η διαδρομή `search` → `product`· το `product` επιστρέφει το `gtin`, που υπήρχε σε 36 από τις 36 σελίδες προϊόντων που ελέγξαμε.
  • Η διαθεσιμότητα δεν έχει παντού το ίδιο λεξιλόγιο: στο `product` είναι `InStock` / `BackOrder`, στο `barcode` είναι `available`.