iHerb API

One product id, thirty storefronts, thirty prices

iHerb sells one catalogue into about 30 countries, and the price is not the same in any two of them.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a iHerb endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
I
/iherb/v1

8 active endpoints, on 1, 2 and 3 credit tiers.

  • POST/iherb/v1/search
  • POST/iherb/v1/category
  • POST/iherb/v1/detail
  • POST/iherb/v1/batch_detail
  • POST/iherb/v1/price_by_country
  • POST/iherb/v1/reviews
  • POST/iherb/v1/categories
  • +1 more

What iHerb endpoints does ReefAPI ship?

8 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

8 endpoints

search

3 cr

Keyword search on one country's storefront.

required
keyword
optional
country, page, page_size, sort, rating_band, brand_codes, category_ids, price_ranges, health_topics, attribute_ids, in_stock_only, programs

category

2 cr

Browse one catalogue category on one country's storefront.

required
slug
optional
country, page, page_size, sort, rating_band, brand_codes, category_ids, price_ranges, health_topics, attribute_ids, in_stock_only, programs

detail

1 cr

One product in full on one country's storefront.

required
product_id
optional
country

batch_detail

3 cr

Up to 20 products in one call, on one storefront.

required
product_ids
optional
country

price_by_country

3 cr

The same product priced across several national storefronts in one call.

required
product_id
optional
countries

reviews

3 cr

Customer reviews for a product, with the per-star breakdown and iHerb's own summary of them.

required
product_id
optional
country, page

categories

1 cr

Every browsable catalogue category iHerb publishes (~1 480).

required
optional
search

filters

2 cr

The filter vocabulary for a keyword or category on one storefront.

required
optional
keyword, slug, country

Every parameter, every allowed value →

iHerb API

3 of 8 endpoints, ready to run

View docs ↗

The same product priced across up to twelve national storefronts in one call — price, ISO currency, the local display price, stock state, and whether the product is listed in that country at all. No currency conversion is applied: every figure is the number iHerb prints in that market.

3 credits1 required · 1 optional
POST/iherb/v1/price_by_country
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the iHerb API works

iHerb is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 280 engines.

02
Call
POST /iherb/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 or 2 or 3 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Find where a supplement is cheapest, and whether you can actually get it there

Cross-border sourcing fails on two things before it fails on price: the product turns out not to be listed in that country at all, or it is listed but out of stock. So the walk ends on availability rather than starting from it.

01search
POST/iherb/v1/search
{"keyword": "vitamin c", "country": "US", "rating_band": 5, "in_stock_only": true}

The five-star band on the US storefront, in stock only — 5,818 products sit in that band before the stock filter. Each row carries the product id you need next, plus the price, currency, brand and rating count.

02price_by_country
POST/iherb/v1/price_by_country
{"product_id": "<id from a search row>", "countries": ["US","GB","DE","JP","AU","SG"]}

One row per storefront with the price, the ISO currency and the stock state. Countries where iHerb does not list the product say so explicitly rather than going missing, which is the answer you need before you plan a route.

03detail
POST/iherb/v1/detail
{"product_id": "<same id>", "country": "<the cheapest market>"}

The full record on that storefront — supplement facts as rows, ingredients, pack size and shipping weight for a landed-cost calculation, plus the restricted-countries list and the banned flag that say whether it can ship where you want it.

A product you know is stocked, priced in each market's own currency with no invented exchange rate, with the pack size and shipping weight to cost the freight and the restriction flags to tell you whether it can legally arrive.

request
curl -X POST https://api.reefapi.com/iherb/v1/price_by_country \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"product_id":1135,"countries":["US","JP"]}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "iherb",
    "endpoint": "price_by_country",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

What changes when you change the country, and what does not

Everything on this page was measured against the live storefronts on one day. The first two rows are the ones that decide whether this API fits what you are building, so they go first.

FieldWhat comes backWhat it means
price_amount + currencyA number and an ISO currency code, always together, never merged into one string. The same product id: US 11.02 USD, GB 12.71 GBP, DE 13.74 EUR, JP 1856 JPY, KR 14460 KRW, AU 23.80 AUD, CA 19.85 CAD, IN 1355.54 INR, BR 79.03 BRL, TR 677.35 TRYThe currency is part of the answer, not something you infer from the country. Ukraine is the row that proves the point: the Ukrainian storefront prices in USD, not the local currency, so a country-to-currency lookup table on your side would have been wrong there. price_display carries iHerb's own formatted string alongside, so you can show exactly what the storefront shows.
rating_countAn integer — but it is shared across a product group, not per variantAgainst us, and worth knowing before you build on it. Products 475 and 16539 are different sizes of the same supplement and both report exactly 25,485 ratings, because iHerb counts reviews per product family. If you sum rating_count across a brand's catalogue you will double-count. Use it per product, not as a total.
supplement_factsRows parsed out of iHerb's nutrition panel — name, amount, daily value. 6 of 6 on vitamin C, probiotics, whey protein and fish oil; 5 of 6 on green tea; 3 of 6 on pet health; 2 of 6 on coffee; 0 of 6 on shampooPresent when the product has a panel and absent when it does not — a shampoo has no supplement facts, so 0 of 6 there is the source being right. The pooled figure across 48 products in 8 categories is 34 of 48, which is why the per-category breakdown is printed rather than the average.
in_stock + stock_status + stock_left_countA boolean, a label (in_stock, in_stock_low, not_available, out_of_stock) and, only when stock is low, a remaining-units integerstock_left_count was null on all 48 US products sampled, because iHerb prints a remaining count only when a product is actually running low — we saw it live on the German storefront as 9 units on a product that was plentiful in the US. Treat it as a low-stock signal, not an inventory feed. back_in_stock_date comes back where iHerb publishes one.
country_of_originAlways nullAgainst us. The field exists in iHerb's data and is empty on all 48 products we sampled, so we return null rather than guessing it from the brand's address. If country of origin is what you need, this API does not have it.
ingredients, suggested_use, warningsPlain text, with iHerb's markup removed. ingredients 44 of 48, suggested_use 48 of 48, warnings 43 of 48iHerb publishes these as HTML fragments; every string this API returns is stripped of tags and entities, checked across 48 product records, a full search payload and a reviews payload. Coffee is the category that thins out — 2 of 6 for ingredients.

Thirty storefronts, 1,483 categories, and the fields iHerb does not publish

Measured against the live engine: 48 product records across 8 categories, prices checked against what each product page itself prints, and every filter measured unfiltered against filtered. The rows that go against us come first.

Against us: country_of_origin is always null, and stock counts are low-stock only

Two fields you might expect and will not get. country_of_origin exists in iHerb's data and was empty on all 48 products sampled, so we return null rather than deriving it from the brand's address. stock_left_count was null on all 48 US products too, because iHerb publishes a remaining-units number only when a product is genuinely low — we saw it live as 9 units on the German storefront for a product that was plentiful in the US. It is a low-stock signal, not an inventory feed. What you do always get is a stock boolean and a status label on 48 of 48.

Against us: rating_count is shared across a product family

Products 475 and 16539 are different sizes of the same supplement and both report exactly 25,485 ratings, because iHerb counts reviews per product group rather than per variant. That is the source's design, not a parsing error, and it means summing rating_count across a catalogue double-counts. Use it per product.

Prices verified against the product pages themselves, 8 of 8

We took eight products across three storefronts and compared every price and currency this API returns against what the product page itself prints for shoppers: 11.02 USD, 18.59 USD, 6.42 USD, 15.99 USD, 8.05 USD, 17.14 USD, 3302 JPY and 40.62 GBP. Eight of eight matched on both the amount and the currency. Ratings were checked against a second independent surface on the same eight products and matched on seven; the eighth differed by three reviews on a product with 387,615 of them, because three arrived between the two calls.

Thirty storefronts, and they are different catalogues rather than one catalogue repriced

The same vitamin C category returns 785 products in the US, 765 in Germany, 755 in Japan, 754 in Singapore, 751 in Canada, 746 in Korea and 736 in the UK. Prices for one product id span $11.02 in the US, 13,74 € in Germany, ¥1,856 in Japan, £12.71 in the UK, ₩14,460 in Korea, ₹1,355.54 in India, R$79,03 in Brazil and ₺677,35 in Turkey. Three countries we tested could not be served and are not offered: Russia, China and Indonesia.

Every filter narrows the result, and two were withheld because they did not

Against an unfiltered 14,940 results: rating band four gives 8,909, brand NOW 756, brand CGN 319, cheapest price band 248, immune-support topic 2,604, vegan 4,820, iTested 273, in-stock-only 14,468. On a category the same holds — 785 down to 346, 36 and 768. Two filters iHerb's own interface advertises are not exposed here: one is accepted and changes nothing at all, the other errors on every value. Exposing a filter that silently does nothing is worse than not having it.

Sorting changes the result set by about 29 percent

Unsorted, a vitamin c search returns 14,807 products. With any explicit sort other than featured or relevance, the same search returns 10,559. This is the source's behaviour, not a paging artefact, and the response flags it so it shows up in your data rather than only here.

Field coverage, counted per category rather than averaged

Across 48 products in 8 categories: product id, SKU, name, brand, price, currency, list price, stock state, rating, rating count, pack size, weight, dimensions, description, suggested use, images, category, breadcrumbs, expiry date and price-per-unit all arrive on 48 of 48. Ingredients 44 of 48, warnings 43 of 48. supplement_facts is 34 of 48 pooled, which is a misleading number on its own: it is 6 of 6 on vitamin C, probiotics, whey protein and fish oil, 5 of 6 on green tea, 3 of 6 on pet health, 2 of 6 on coffee and 0 of 6 on shampoo — a shampoo has no nutrition panel.

Reviews are public, paged ten at a time, with the full star breakdown

No account is involved. Each page carries ten reviews with text, title, star rating, date, language, verified-purchase flag, helpful votes and attached photo count, plus the average, the total and the per-star split — 6,580 ratings on product 468, split 5,314 / 871 / 305 / 52 / 38 from five stars down to one, across 653 pages. iHerb's own written summary of the reviews comes back alongside. Reviewer display names are off by default and opt-in; handles and avatars are never returned.

Ids round-trip, and the discount is computed rather than trusted

Six product ids taken from a search and resolved through detail came back with the same id, the same type, the same SKU and the same price to the cent, six times out of six. Where a product is discounted you get the price, the list price and a discount percentage we compute from those two, kept separate from iHerb's own discount figure so that if the source's number ever disagrees with its own prices you can see both instead of having to trust one.

What people build with iHerb

The jobs this data is most often used for.

8

endpoints

1/2/3

credits per call

01

Price a product across borders before you launch there: give price_by_country one product id and a dozen markets and get back the price, currency, availability and local display string for each, so you can see what iHerb charges in a market before you set your own price against it.

02

Watch a competitor's supplement range in one country: run a category or brand-filtered search on that storefront and store price_amount with its currency, the rating and the rating count, then re-run it on a schedule to follow price moves and review growth.

03

Build a supplement comparison or ingredient search: pull supplement_facts as rows plus the ingredient text across a category and compare dosage per serving between brands, using price_per_unit and pack size to get a real cost per serving rather than a cost per bottle.

04

Check where a product is actually sold: price_by_country tells you which storefronts list an item and which do not, and each record carries the restricted-countries list and a banned flag, which is the difference between a product you can source and one you cannot.

What iHerb data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 280 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/iherb/v1/price_by_country \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"product_id":1135,"countries":["US","JP"]}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/iherb/v1/price_by_country",
    headers={"x-api-key": REEF_KEY},
    json={
  "product_id": 1135,
  "countries": [
    "US",
    "JP"
  ]
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up iHerb.

Get a free key →
How do I get the price in a specific country?

Pass country on any call — search, category, detail, batch_detail or reviews all take it, and it defaults to US. Thirty storefronts are supported: US, CA, MX, BR, GB, DE, FR, IT, ES, NL, PL, SE, TR, UA, IL, AE, SA, ZA, IN, JP, KR, HK, TW, SG, MY, TH, VN, PH, AU and NZ. Every response repeats the country and the ISO currency it was priced in, so a stored row can never lose track of which storefront it came from. If a storefront cannot be reached for a request, the call fails with a clear error instead of quietly answering from a different country — a price in the wrong currency is worse than no price.

Can I compare one product across several countries in one call?

That is what price_by_country does. Give it a product id and up to twelve country codes and it returns one row per storefront with the price, the ISO currency, the local display price, the stock state and whether the product is listed there at all. Products are not on every storefront — when one is missing, that row says so rather than being dropped, so you can see where a product is simply not sold. No currency conversion is applied anywhere in this API: each figure is the number iHerb itself prints in that market, because an FX rate we invented would be the least reliable number on the page.

Are the reviews real reviews, or just the rating?

Real reviews, and no account is involved in reading them. Each page returns ten with the review text, the title, the star rating, the date, the language, the verified-purchase flag, the helpful-vote counts and how many photographs are attached. Alongside them you get the average, the total, and the full per-star breakdown — for product 468 that is 6,580 ratings split 5,314 five-star, 871 four, 305 three, 52 two and 38 one — plus iHerb's own written summary of what customers said. Product 468 runs to 653 pages of reviews. Reviewer display names are withheld by default and returned only if you explicitly ask for them; handles and avatars are never returned.

Do the filters actually narrow the results, or are they accepted and ignored?

Every filter this API exposes narrows the result, and we publish the proof. Against an unfiltered 14,940 results for vitamin c: the four-star band returns 8,909, the NOW Foods brand 756, California Gold Nutrition 319, the cheapest price band 248, the immune-support health topic 2,604, the vegan attribute 4,820 and the iTested programme 273. In-stock-only takes 14,940 to 14,468. Two filters that iHerb itself advertises are deliberately not exposed here: one is accepted and changes nothing, and the other returns an error for every value. Rather than pass those through and let you believe they worked, we left them out.

Why is the rating filter called rating_band and not min_rating?

Because it is a band and not a minimum, and the honest name saves you a wrong result. Asking for band 3 returns products rated roughly 2.8 to 3.7 — it excludes the four- and five-star products, rather than including everything above three. Measured on one storefront: band 5 returns 5,818 products rated about 4.8 and up, band 4 returns 8,909 rated roughly 3.8 to 4.7, band 3 returns 36, band 2 returns 6 and band 1 returns 2. The filters action prints the live count sitting behind each band so you can see the shape before you query.

Does sorting just reorder the results?

No, and this one surprised us enough to put it in the response. Unsorted, vitamin c returns 14,807 results; sorted by price, by rating, by newest or by any other explicit sort, the same query returns 10,559. Sorting changes which products are in the set by about 29 percent, it does not merely change their order. The search response carries a sorted_population_differs flag so this is visible in the data rather than only in the documentation. Featured and relevance are the two that leave the total alone.

How do I find the brand codes and attribute ids the filters want?

Call the filters action with a keyword or a category slug. It returns iHerb's own vocabulary for that query with a live product count beside every option: 1,056 brands, 1,349 category ids, plus health topics, price bands, programmes and the attribute groups that cover diet and certification, product form, age range and skin or hair concern. That is 28 filter groups and 2,725 options on a single query. The codes are opaque — NOW Foods is NOW, 100% PURE is URE — so reading them from this call is the only reliable way to get them right.

How do I get product ids in the first place?

Three ways, and none of them needs you to know an id in advance. Search by keyword; browse a category, with all 1,483 category slugs available from the categories action; or, if you already have an iHerb URL, the id is the last path segment. Search also resolves a SKU or part number directly, so a query that exactly matches a product comes back flagged as an exact match. A search row and a detail record agree: we checked six ids from search through to detail and got the same id, the same type, the same SKU and the same price to the cent on all six.

What is the iHerb API?

iHerb API is a ReefAPI endpoint group for supplements and natural health, priced in 30 countries. It returns live JSON through POST requests under /iherb/v1.

Is the iHerb API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. iHerb calls use the same shared credit balance as every other ReefAPI engine.

Do I need an iHerb login or account?

No login to iHerb is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the iHerb data?

The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the iHerb API use?

iHerb actions currently cost 1-3 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.

Can I call iHerb from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call iherb actions with the same key, credit pool and JSON envelope used by normal REST requests.

116 E-commerce & Marketplaces APIs on the same key

One key, one credit pool, one response envelope. If you are pulling iHerb, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 279 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-09-23.