Radar de Precios
Live usableI match 296 medicines across Peruvian pharmacy chains by reading their own undocumented APIs.
Compares the price of the same medicine across Peruvian pharmacy chains. It solves the hard part: deciding that two different SKUs are the same product, by code and by active ingredient.
Technology
- Scraping
- Data viz
Sector
- Health
- Retail & business
Problem
The same medicine can cost 20-70% more at one Peruvian pharmacy chain than another, and two of the country's three largest chains belong to the same holding company — nothing forces price transparency, and no public tool lets a buyer compare instantly before they walk into a store.
Approach
Per-chain adapters over undocumented APIs (Algolia, SFCC) and a three-layer matcher that decides, without a shared product catalog, when two listings are the same medicine.
Inkafarma and Mifarma belong to the same holding and run on the holding’s own Algolia search, so their listings share an internal product ID and match for free. Boticas Perú runs on Salesforce Commerce Cloud instead, with no shared ID at all — its adapter combines the public HTML product grid with the storefront’s own QuickView JSON. None of these are official APIs: each adapter reads the same public, search-only client keys and endpoints the chains’ own storefronts call from the browser, throttled well below anything that would look like abuse.
Matching across chains with no shared ID is the actual problem the project solves. The matcher runs in three layers: exact ID where it exists, fuzzy matching on name, active ingredient and pack size (guarded against bundles and near-miss variants like different vitamin doses) where it doesn’t, and perceptual image hashing as a final check on doubtful fuzzy matches. Every run is kept as its own snapshot rather than overwritten, so price history and promo detection are possible later without re-scraping the past.
The published site is deliberately boring: static HTML/CSS/JS with no build step, reading a JSON file at runtime and rendering the comparison table client-side, so it costs nothing to host and drops into any subdirectory unchanged.
Result
- products matched across chains
- 296
- matched with a Boticas Perú price
- 100
- matched in all three chains
- 64
web/data.json
web/data.json
web/data.json
Standards
| Software quality (ISO/IEC 25010) | Not run through a formal ISO/IEC 25010 checklist. The hardest quality risk — false product matches — is addressed directly: a three-layer matcher (exact ID, fuzzy text, perceptual image hash) with documented guards against bundles and near-miss variants. |
|---|---|
| Web performance (Core Web Vitals) | not measured |
| Accessibility (WCAG 2.2) | not measured |
| Research software (FAIR4RS) | n/a — not research software |
| Security hygiene | Only public, search-only Algolia keys are used (visible in each chain's own JS bundle); README confirms none were ever committed across the repo's 34 commits. |
| Reproducibility | requirements.txt pinned; .env.example documents the required credentials; one pytest module covers the matcher. No container yet. |
| Benchmark methodology | no benchmark claimed |
| Data / model documentation | n/a |
| Versioning & change log | No SemVer; plain commit history (34 commits) on a public repo. |
What I'd do next
- Add price history from the kept per-run snapshots, instead of showing only the latest run.
- Automate the scheduled run (currently manual) and alert on promo-driven price swings.
- Extend the matcher to a fourth chain once an adapter for its storefront exists.