How we measure
Version 1.0.0, updated 2026-08-29. Public name of the score: Structural Verification Index. Every number on this site can be recomputed from the published data and the rules on this page: the engine reads the same file this page is rendered from.
What we check — and what we do not
We check structural trust facts against official public registers: who the responsible physician is, what certification and licence the registers confirm, whether the facility and the legal entity can be traced, whether the clinic discloses its own identifiers, whether its advertising is honest, whether its language fronts agree, and whether patient documents are published.
We do not assess outcomes, skill or complications. A high score means the clinic is well verified, not that treatment there is right for you. This is not medical advice.
The unit
One record = one clinic in this country: brand + address + responsible physician. The named physician is the load-bearing field — every register check is by name. Procedure segment and city are facets, not units.
Inclusion policy
Four mechanical conditions. The first three decide whether a clinic is listed; the fourth whether it can be scored.
- Identifiable: a live public surface and a working in-country contact on the check date.
- Provides the service itself: not an aggregator, booking site, affiliate or tour packager.
- In scope: the intervention is performed by a physician — plastic or aesthetic surgery, hair transplant, physician-led injectables or device treatments, medical weight loss. Out: salons, barbers, nails/brows/lashes, spas, med-spas without a named physician.
- Names a responsible physician. Otherwise the record is published as verification unavailable: listed, not scored, no rank. Unknown is not fault — a missing name is a statement about coverage, not an accusation.
Country register map
The map for Croatia was compiled 2026-08-29, before any clinic research. A class marked as absent makes its axis not applicable; a register that cannot be scripted leaves its axis cells as 'could not verify', without penalty. We never simulate a register.
| Specialist board register | Hrvatska liječnička komora (HLK) — Imenik liječnika (Register of Physicians); public disclosure is limited by AZOP/Information-Commissioner opinion to member name + 'područje važeće licence' (area of valid licence), which is where specialisation such as plastična kirurgija shows (open, machine-readable) First pass recorded 'login' after a GET to /imenik-lijecnika/?searchtext=... came back with 'Nemate dozvole za prikaz ovih zapisa'. That string is a static placeholder baked into the Power Pages shell, not a server verdict; the underlying grid service answers anonymously. SCRIPTED RECIPE (verified 2026-08-29, plain curl / Node fetch, no browser, no login, no CAPTCHA). The portal is a Power Pages site whose 'Nemate dozvole za prikaz ovih zapisa' / 'Ne postoje zapisi za prikaz' strings are static client-side template placeholders sitting in the page shell — they are NOT the server's answer, which is why a naive GET with ?searchtext= looks permission-denied. The list is a Dataverse entity list (entity cr501_imeniklijecnika, view 0b4da236-014e-ed11-bba2-000d3aabc1e3) served by the portal's entity-grid-data service. Three steps: (1) GET https://hlkhr.powerappsportals.com/imenik-lijecnika/ with a browser User-Agent, keeping cookies (Dynamics365PortalAnalytics, ARRAffinity, ARRAffinitySameSite); from the HTML take the grid GUID out of `entity-grid-data.json/<guid>` (currently a0f1c80e-a24b-ed11-bba1-002248847e8b) and the attribute data-view-layouts='<base64>', base64-decode it to a JSON array and keep [0].Base64SecureConfiguration. (2) GET https://hlkhr.powerappsportals.com/_layout/tokenhtml with the same cookies and read the value="..." of the __RequestVerificationToken input. (3) POST https://hlkhr.powerappsportals.com/_services/entity-grid-data.json/a0f1c80e-a24b-ed11-bba1-002248847e8b with those cookies, header __RequestVerificationToken: <token>, Content-Type: application/json, body {"base64SecureConfiguration":"<from step 1>","sortExpression":"","search":"Bagatin","page":1,"pageSize":50,"filter":null,"metaFilter":null,"timezoneOffset":-120,"customParameters":[]}. Returns HTTP 200 JSON {MoreRecords, ItemCount, PageCount, Records:[{Attributes:[...]}]}; the useful attributes are cr501_ime, cr501_prezime, cr501_imeiprezime, cr501_hlkid (HLK member number, form HR######), cr501_licenciranopodrucje ('Licencirano područje' = area(s) of valid licence, i.e. the specialisation cell) and statecode/statuscode (both 'Aktivno' for a live entry). The __RequestVerificationToken header is mandatory — omitting it returns HTTP 500. The portal's own tooltip documents '*' as the wildcard for partial-text search. The row-level 'Detalji' modal is a separate Power Pages entity form and was NOT needed: the grid response already carries name + HLK id + licensed area + active state. portal.hlk.hr/imenik-lijecnika/ is only a 1.5 KB frame around the same hlkhr.powerappsportals.com app — query the powerappsportals host directly. Field set now confirmed: public disclosure is exactly member name + HLK id + 'licencirano područje', matching the AZOP / Information-Commissioner limitation described on hlk.hr/imenik-lijecnika.aspx — no address, birth date or employer. Usable for M1 (specialisation) with official provenance; the specialisation string is free text listing every licensed area, so match on substring ('plastična kirurgija'), not equality. |
|---|---|
| Medical licence register | Hrvatska liječnička komora (HLK) — Imenik liječnika, same register: licence status / 'područje važeće licence' (odobrenje za samostalan rad) (open, machine-readable) Identical service and backend to specialist_board — one HLK register feeds both M1 and M3. Licence evidence available per record: presence in the Imenik + cr501_licenciranopodrucje (area of valid licence) + statecode/statuscode 'Aktivno'. No licence expiry date and no licence number beyond cr501_hlkid is exposed in the grid payload, and the row-level 'Detalji' entity form was not needed to obtain the above. SCRIPTED RECIPE (verified 2026-08-29, plain curl / Node fetch, no browser, no login, no CAPTCHA). The portal is a Power Pages site whose 'Nemate dozvole za prikaz ovih zapisa' / 'Ne postoje zapisi za prikaz' strings are static client-side template placeholders sitting in the page shell — they are NOT the server's answer, which is why a naive GET with ?searchtext= looks permission-denied. The list is a Dataverse entity list (entity cr501_imeniklijecnika, view 0b4da236-014e-ed11-bba2-000d3aabc1e3) served by the portal's entity-grid-data service. Three steps: (1) GET https://hlkhr.powerappsportals.com/imenik-lijecnika/ with a browser User-Agent, keeping cookies (Dynamics365PortalAnalytics, ARRAffinity, ARRAffinitySameSite); from the HTML take the grid GUID out of `entity-grid-data.json/<guid>` (currently a0f1c80e-a24b-ed11-bba1-002248847e8b) and the attribute data-view-layouts='<base64>', base64-decode it to a JSON array and keep [0].Base64SecureConfiguration. (2) GET https://hlkhr.powerappsportals.com/_layout/tokenhtml with the same cookies and read the value="..." of the __RequestVerificationToken input. (3) POST https://hlkhr.powerappsportals.com/_services/entity-grid-data.json/a0f1c80e-a24b-ed11-bba1-002248847e8b with those cookies, header __RequestVerificationToken: <token>, Content-Type: application/json, body {"base64SecureConfiguration":"<from step 1>","sortExpression":"","search":"Bagatin","page":1,"pageSize":50,"filter":null,"metaFilter":null,"timezoneOffset":-120,"customParameters":[]}. Returns HTTP 200 JSON {MoreRecords, ItemCount, PageCount, Records:[{Attributes:[...]}]}; the useful attributes are cr501_ime, cr501_prezime, cr501_imeiprezime, cr501_hlkid (HLK member number, form HR######), cr501_licenciranopodrucje ('Licencirano područje' = area(s) of valid licence, i.e. the specialisation cell) and statecode/statuscode (both 'Aktivno' for a live entry). The __RequestVerificationToken header is mandatory — omitting it returns HTTP 500. The portal's own tooltip documents '*' as the wildcard for partial-text search. The row-level 'Detalji' modal is a separate Power Pages entity form and was NOT needed: the grid response already carries name + HLK id + licensed area + active state. portal.hlk.hr/imenik-lijecnika/ is only a 1.5 KB frame around the same hlkhr.powerappsportals.com app — query the powerappsportals host directly. |
| Facility register | Hrvatski zavod za javno zdravstvo (HZJZ) — Nacionalni registar pružatelja zdravstvene zaštite (NRPZZ): healthcare institutions, trading companies performing healthcare activity, and private-practice holders, recorded from Ministry of Health work-approval decisions (open, machine-readable) Not a live query endpoint — it is a periodically republished full-list Excel download (filename carries the as-of date, 20.05.2026 at research time), so 'searchBy' means filtering the downloaded workbook locally, not a URL query string. No CAPTCHA or login anywhere in the flow. Corrections go to [email protected]. |
| Company register | Sudski registar (Ministarstvo pravosuđa i uprave) — Pretraga subjekata (Commercial Court Register: d.o.o./j.d.o.o./d.d./cooperatives etc.); Obrtni registar (pretrazivac-obrta.gov.hr) is the parallel public register for sole-trader craft-registered practices (obrt), not tested here (open, machine-readable) First pass recorded 'form' because a GET with the query in the URL returns the blank form. That observation is right about URL params but wrong about scriptability: the APEX page submit reproduces over plain HTTP with no browser, so access is 'open'. SCRIPTED RECIPE (verified 2026-08-29, Node fetch with a cookie jar, no browser, no login, no CAPTCHA). sudreg.pravosudje.hr/registar/f?p=150:1 now 302s to an Oracle APEX 23.2 app at /ords/r/esudreg/public/pretraga-subjekata (app 250, page 1). URL-bound page items do NOT work (P1_NAZIV in the query string only pre-fills the box) but a plain HTTP page submit does. Four steps: (1) GET https://sudreg.pravosudje.hr/ords/r/esudreg/public/pretraga-subjekata following redirects and keeping cookies (ORA_WWV_APP_250 etc.); scrape the hidden inputs pFlowId (250), pFlowStepId (1), pInstance (session id), pPageSubmissionId, pSalt, pPageItemsProtected and the form action wwv_flow.accept?p_context=public/pretraga-subjekata/<session>. (2) POST https://sudreg.pravosudje.hr/ords/wwv_flow.accept?p_context=public/pretraga-subjekata/<session>, application/x-www-form-urlencoded, fields p_flow_id, p_flow_step_id, p_instance, p_page_submission_id, p_request=PRETRAZI, p_reload_on_submit=A and p_json={"pageItems":{"itemsToSubmit":[{"n":"P0_THEME_STYLE_ID","v":"Egradani"},{"n":"P1_OPERATOR","v":"contains"},{"n":"P1_NAZIV","v":"BAGATIN"},{"n":"P1_STATUS_SUBJEKTA","v":""},{"n":"P1_MBS","v":""},{"n":"P1_OIB","v":""},{"n":"P1_U_STECAJU","v":""},{"n":"P1_PRAVNI_OBLIK","v":""},{"n":"P1_SUD","v":""},{"n":"P1_STALNE_SLUZBE","v":"D"},{"n":"P1_PRETRAZI","v":"0"},{"n":"P1_HIDE","v":"0"}],"protected":"<pPageItemsProtected>","rowVersion":"","formRegionChecksums":[]},"salt":"<pSalt>"}. GOTCHA: P1_OPERATOR values are lowercase — contains | begins | ends | app_begins | app_contains; sending 'CONTAINS' makes the report raise ORA-06592 'CASE not found while executing CASE statement'. (3) The 302 lands back on page 1, now carrying the 'Rezultati pretraživanja' region; from that HTML take the interactive-report region id (currently R325874759093906821), its "ajaxIdentifier" from the apex.jQuery('#<region>_ir').interactiveReport({...}) init (un-escape the \u002F back to /), and the hidden inputs <region>_worksheet_id (325875559141906829) and <region>_report_id. (4) POST https://sudreg.pravosudje.hr/ords/wwv_flow.ajax, application/x-www-form-urlencoded, fields p_flow_id=250, p_flow_step_id=1, p_instance=<session>, p_debug=, p_request=PLUGIN=<ajaxIdentifier>, p_widget_name=worksheet, p_widget_mod=ACTION, p_widget_action=PAGE, p_widget_num_return=100, x01=<worksheet_id>, x02=<report_id>. Returns the report HTML table with columns MBS | OIB | Sud | Status | Naziv / Ime subjekta | Status naziva | Adresa (historic name variants come back as extra rows marked 'Promijenjeno'). Searching by OIB or MBS instead of name just means filling P1_OIB / P1_MBS and leaving P1_NAZIV empty. Two other Croatian legal-entity sources were probed this pass and rejected as gated: (a) the official bulk REST API documented at https://sudreg-data.gov.hr/api/javni/dokumentacija/open_api (OpenAPI 3.0.1, 'Sudski registar api - javni' v3.0.4, 40 endpoints incl. /subjekti, /detalji_subjekta, /sjedista, /pretezite_djelatnosti, /snapshots) — the spec itself is fully public and anonymously readable, but every data endpoint answers HTTP 401 anonymously; it needs an OAuth2 client-credentials account registered at https://sudreg-data.gov.hr/ords/r/srn_rep/vanjski-srn-rep/home, so it is not usable unauthenticated and no open bulk dump was found there; (b) sudreg-api.pravosudje.hr does not resolve (DNS failure). Obrtni registar (pretrazivac-obrta.gov.hr), the parallel register for sole-trader craft practices (obrt), was again not tested. |
| Sanctions / discipline register | no public register of this class in this country |
| Foreign-patient register | no public register of this class in this country |
The nine axes
Every axis is a fact or a quote from a public source, scored 1–5 against a fixed rubric. There are no editorial axes. Each cell carries its sources, its source class (official register / secondary) and its check date.
Fame, review volume, domain age and social-media following are scored nowhere.
M1 · Specialist certification of the responsible physician — weight 26
Whether the physician named as responsible for this clinic is found in the country's specialist board register with a current specialisation matching the advertised segment (plastic surgery or dermatology, by segment).
Register class: Specialist board register — Hrvatska liječnička komora (HLK) — Imenik liječnika (Register of Physicians); public disclosure is limited by AZOP/Information-Commissioner opinion to member name + 'područje važeće licence' (area of valid licence), which is where specialisation such as plastična kirurgija shows.
| Value | Anchor |
|---|---|
| 5 | Found by name or number; specialty matches what is advertised; status current. |
| 4 | Found; specialty adjacent to what is advertised (noted on the profile). |
| 3 | Found in the register; the register does not disclose specialty. |
| 2 | Only a secondary source (association, aggregator) supports the certification. |
| 1 | Certification is claimed and found in no source. |
M2 · Identifiability of the responsible physician — weight 16
Whether a patient can name the specific physician and their role before making contact, and whether that physician is tied to this location.
| Value | Anchor |
|---|---|
| 5 | Physician(s) named with role and tied to this address. |
| 4 | Named; role unclear. |
| 3 | A name appears in only one place on the site. |
| 2 | Surname or initials without a full name. |
| 1 | 'Our team' only — this is the gate state 'verification unavailable'. |
M3 · Basic medical licence — weight 8
Whether the responsible physician's registration is found in the country's medical licence register.
Register class: Medical licence register — Hrvatska liječnička komora (HLK) — Imenik liječnika, same register: licence status / 'područje važeće licence' (odobrenje za samostalan rad).
| Value | Anchor |
|---|---|
| 5 | Matched by licence number. |
| 4 | Matched by name. |
| 3 | Register not machine-accessible; the clinic publishes the number. |
| 2 | Licence claimed without a number. |
| 1 | Public data contradicts the claim. |
M4 · Facility registration — weight 10
Whether the operating location is found in the facility register (where the country has one; otherwise this axis is not applicable).
Register class: Facility register — Hrvatski zavod za javno zdravstvo (HZJZ) — Nacionalni registar pružatelja zdravstvene zaštite (NRPZZ): healthcare institutions, trading companies performing healthcare activity, and private-practice holders, recorded from Ministry of Health work-approval decisions.
| Value | Anchor |
|---|---|
| 5 | Record found: name, address and status match. |
| 4 | Record found with a spelling discrepancy. |
| 3 | Register exists; no record found (we do not claim 'unlicensed'). |
| 2 | Only the clinic's own statement. |
| 1 | A published registration number is contradicted by the register (verified false → flag). |
M5 · Legal-entity traceability — weight 8
Who is legally responsible: a legal entity in the company register, tied to the brand and the address.
Register class: Company register — Sudski registar (Ministarstvo pravosuđa i uprave) — Pretraga subjekata (Commercial Court Register: d.o.o./j.d.o.o./d.d./cooperatives etc.); Obrtni registar (pretrazivac-obrta.gov.hr) is the parallel public register for sole-trader craft-registered practices (obrt), not tested here.
| Value | Anchor |
|---|---|
| 5 | Legal entity and registration number published and matched in the register. |
| 4 | Matched by name. |
| 3 | Legal entity named; register not accessible. |
| 2 | Brand only. |
| 1 | No legal entity found after a full pass (verified conflict → hold H2). |
M6 · Self-disclosure of identifiers — weight 10
Whether the clinic itself publishes the numbers needed to re-check it (licences, certificates with issuer). Disclosure is rewarded; a missing number is not a missing licence.
| Value | Anchor |
|---|---|
| 5 | All load-bearing numbers published with issuers. |
| 4 | Physician numbers published; facility or legal-entity numbers not. |
| 3 | Partial, without issuers. |
| 2 | Logos without numbers. |
| 1 | No identifiers at all. |
M7 · Advertising honesty — weight 12
A machine profile of the clinic’s own claims: outcome guarantees, ‘100% safe’, ‘No. 1’ or ‘best’ without an issuer, ‘unlimited grafts’, before/after presented as a promise, foreign boards presented as the national specialist board. Every deduction cites an exact quote with URL, locale and date.
| Value | Anchor |
|---|---|
| 5 | No pattern from the lexicon found. |
| 4 | One or two soft superlatives. |
| 3 | Systematic superlatives without guarantees. |
| 2 | Guarantee or ‘100%’-class statement (bright line; cap candidate). |
| 1 | Verified fake credential (flag + cap). |
M8 · Cross-locale consistency — weight 5
Whether facts agree across the language fronts of the clinic's own site (physician, numbers, accreditations) — a mechanical comparison of extracted fields.
| Value | Anchor |
|---|---|
| 5 | All load-bearing fields agree. |
| 4 | Spelling discrepancies. |
| 3 | Some facts appear on only one front. |
| 2 | A load-bearing fact (physician or number) differs. |
| 1 | Fronts contradict each other on credentials (H2 candidate). |
M9 · Patient documents — weight 5
Presence check for five document classes: informed consent, risks/contraindications, aftercare, revision policy, complaint route. Presence only — the quality of the documents is not assessed.
| Value | Anchor |
|---|---|
| 5 | All five classes published. |
| 4 | Four. |
| 3 | Two or three. |
| 2 | One. |
| 1 | None. |
The formula
Each axis value 1–5 is mapped to 0–1. The composite is the weighted average over the axes that hold a value: axes that are not applicable in this country and axes we could not verify drop out of the normalisation.
composite = 100 × Σ(weight × (value − 1) / 4) / Σ(weight of axes with a value) score = min(composite + focus adjustment, lowest active ceiling), clamped to 0…100
Coverage threshold: a score is published only when at least 75% of the applicable axis weight holds a sourced value. Below that the record shows 'verification pending' and carries no rank.
Focus adjustment
A mechanical classification from the clinic's own menu.
| Focus | Adjustment |
|---|---|
| specialist | 0 |
| aesthetic in general clinic | -2 |
| spa or salon addon | -5 |
Score ceilings
A ceiling is applied only from a verified-false finding — never from 'not found'. Each ceiling is rendered from a fixed template with the exact quote or register entry and its URL; no free text is written about a named clinic.
| Ceiling | Max score | What triggers it | Fixed wording |
|---|---|---|---|
| Verified false accreditation or licence claim | 45 | A claimed accreditation, board certification or licence is contradicted by the official register. Never applied on 'not found' alone. | The register {registry} (record dated {date}) does not confirm the credential claimed at {url}: “{quote}”. Under this methodology the score is capped at {cap}. The clinic has been offered a right of reply. |
| Outcome guarantee or ‘100% safe’-class statement | 65 | The clinic's own published text guarantees a result or absolute safety. Applied only with the exact quote. | The clinic's own page {url} ({locale}, {date}) states: “{quote}”. Under this methodology an outcome guarantee caps the score at {cap}. |
| Active sanction in a machine-readable official register | 45 | Exists only in countries whose registry map declares a sanctions register. Absence of a sanction is never a finding. | Entry in the {registry} register dated {date}: {url}. The score is capped at {cap} and the profile is held pending the clinic's right of reply. |
The sanctions ceiling exists only in countries with a machine-readable official sanctions register. In this country: no public register of this class in this country. Absence of a sanction is never a finding.
Holds
Positive verification by default; the hold ladder handles the cases where public records conflict or the physician cannot be identified.
| ID | Hold | Effect | Fixed wording |
|---|---|---|---|
| H1 | Clarification requested | profile provisional, no crown | A clarification has been requested from the clinic. The profile is provisional and carries no crown until it is resolved. |
| H2 | Material structural conflict | ceiling after the right-of-reply window (69), 14-day right-of-reply window | Public records show a material structural conflict ({detail}). After the right-of-reply window the score is capped at {cap}. |
| H3 | Responsible physician not identifiable | composite withheld, unranked | The responsible physician could not be identified from public sources. The composite score is withheld and the clinic is listed without a rank. |
Crowns and procedure slices
A crown is a boolean gate from register-verified axes — never from a clinic's claim. Within a crown, the order is the composite.
| Crown | Meaning | Gate |
|---|---|---|
| Specialist-led | The responsible physician holds a current, matching specialist certification in the official register (M1 = 5, official source) and is clearly identifiable (M2 ≥ 4). | M1 ≥ 5 (official register) · M2 ≥ 4 |
| Foreign-patient ready | The clinic is verified in the country's official foreign-patient register. Exists only where such a register exists. | no such register in this country — this crown does not exist here |
Procedure slices list the clinics whose own menu names the procedure (a sourced boolean), ranked by the composite:
Outcome quality
There is no independent measurement of treatment outcomes in this field, and we do not imitate one. The register facts already in the axes are the only quality-adjacent evidence we publish.
How the data is produced (unattended run)
- No score without a source — in two passes. A collector records the value, the quote and the URL; a separate verifier reloads the URL and looks for the quote by string match. If the quote is not found, the cell degrades to 'could not verify'.
- All negative wording is templated. Ceilings and holds are rendered from fixed strings plus the cited quote or register entry. Nothing free-form is written against a named clinic.
- The validator is the build gate. Every axis key must be present (null allowed, absence not), every citation must resolve, ceilings only from verified-false findings with a quote, weights must sum to 100, and superlatives in our own text fail the build.
- A checklist per record: at least two independent sources, the register map opened and cited, every axis either a sourced value or an explicit 'could not verify'.
- Right of reply without a human in the loop: messages to the contact form or corrections@ are processed as ordinary data input. A correction with a source is applied and logged; a statement without one is published next to the data and the score does not change.
Freshness
Each record shows the real date of its last check. Register axes (M1, M3, M4) are rechecked within 90 days; the advertising axis (M7) within 180 days. Every change is logged in the changelog and in the record's own history.
What this register does not do
- We do not measure treatment outcomes, surgical skill or complication rates.
- We do not see clinics without a public web presence.
- Register classes this country does not publish are named as unavailable; we never simulate a register.
- We take no money from clinics, we do not book, and we do not refer.
- Fame, review volume, domain age and social-media following are not scored anywhere.
Independence: we take no money from clinics, we do not book, we do not refer, and no position can be bought. Data changes only through sourced facts, for every clinic under the same rules.
This site is an independent research project provided 'as is'. Clinic names and public information are used for identification. Nothing here creates a doctor–patient or advisory relationship.
Methodology versions
| Date | Version | Change |
|---|---|---|
| 2026-08-29 | v1.0.0 | Initial public methodology: nine mechanical axes (M1–M9, weights summing to 100), 1–5 rubric per axis, weighted composite normalised over axes that hold a value, 75% coverage threshold, hold ladder H1–H3, score caps only from verified-false findings, focus penalty, registry-gated crowns. |