Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the Migros Sanalmarket API page →
E-commerce & Marketplaces

Migros Sanalmarket API & Scraper

The Migros API turns Migros Sanalmarket, the online grocery of Turkey's largest supermarket chain, into clean JSON in seven actions: search, product/detail, product/barcode, deals, category, categories and suggest.

7 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

Every product comes back with two prices kept apart - price, what a shopper without a Money loyalty card pays, and member_price, the Money-card price - because the number Migros displays is the member price whenever a Money promotion runs. On 2026-09-15 the products flagged with a member price were exactly the products on Migros's own Money discount list: 73 of 73 for the keyword peynir, no difference either way. Rows also carry the unit price per kg or litre re-based on the non-member price, whether the product is sold by the piece or by weight, availability, the order cap, multi-buy offers such as 2.si %80, clearance flags, basket-only discounts kept out of the price, brand and the full category path. product/detail adds every image, the label sheet as structured specs (ingredients, allergen warning, net quantity, origin, storage), and the supplier details Migros is required to show. Verification on 2026-09-15: 20 of 20 searches and 30 of 30 product reads succeeded, 37 of 37 controlled cases passed, 7 of 7 products matched an independent read of the source on title, price, member price and availability, and search rows agreed with product records on 30 of 30 products. Prices are TRY. No Migros account needed - one ReefAPI key and the standard { ok, data, meta, error } envelope.

Reference

The price Migros displays is the Money-card price whenever a Money promotion runs

This is the one thing to know before you build a Turkish grocery price tracker on Migros. When a Money promotion is active, the price shown on the shelf is the loyalty-card price; a shopper without the card pays more. The API returns both, and never merges them. Measured on 2026-09-15.

Migros productprice (no Money card)member_price (Money card)Unit price, no card / with card
Bahçıvan Çeçil Peyniri 200 G229.95 TRY149.90 TRY1,149.75 / 749.50 TRY per kg
Kahve Dünyası Tambol %85 Kakao Bitter Çikolata 77 G99.90 TRY69.90 TRYper-kg price re-based the same way
Torku Bitter Çikolata 60 G69.95 TRY59.90 TRYper-kg price re-based the same way
Torku Tam Yağlı Taze Kaşar Peyniri 600 G479.90 TRYnull - no Money promotion799.83 TRY per kg
Akpınar Taze Beyaz Peynir Kg429.00 TRY per kg (sold by weight)nullnull - the price is already per kg

member_discount_percent is computed from the two prices and equalled Migros's own discount figure (35 percent on the first row). The unit price Migros prints is calculated on the member price; unit_price is re-based on the non-member price and the printed figure is returned as member_unit_price. A basket discount such as "Sepette %20 İndirim" is applied only in the basket, so it is returned in basket_discounts and never subtracted from price.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/migros/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "peynir"
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "migros",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 525.8,
    "record_count": 30,
    "bytes": 80652,
    "cache_hit": false,
    "pagination": {
      "page": 1,
      "has_more": true,
      "page_size": 30,
      "total": 454
    }
  },
  "data": {
    "results": [
      {
        "product_id": "10406815",
        "store_product_id": "20000010406815",
        "title": "Bahçıvan Çeçil Peyniri 200 G",
        "brand": {
          "id": 729,
          "name": "Bahçıvan",
          "url": "https://www.migros.com.tr/bahcivan-b-2d9"
        },
        "category": {
          "id": 10046,
          "name": "Yöresel Peynir",
          "url": "https://www.migros.com.tr/yoresel-peynir-c-273e"
        },
        "breadcrumb": [
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          }
        ],
        "url": "https://www.migros.com.tr/bahcivan-cecil-peyniri-200-g-p-9ecb9f",
        "image": "https://images.migrosone.com/sanalmarket/product/10406815/10406815_1-701de7-1650x1650.jpg",
        "price": 229.95,
        "price_display": "229,95 TL",
        "currency": "TRY",
        "original_price": null,
        "original_price_display": null,
        "discount_percent": null,
        "member_price": 149.9,
        "member_price_display": "149,90 TL",
        "member_discount_percent": 35,
        "member_program": "Money",
        "unit_price": 1149.75,
        "unit_price_unit": "Kg",
        "member_unit_price": 749.5,
        "sold_by": "piece",
        "price_per": "piece",
        "availability": "in_stock",
        "in_stock": true,
        "max_order_quantity": 8,
        "max_order_grams": null,
        "order_step_grams": null,
        "min_order_grams": null,
        "badges": [
          {
            "type": "[trimmed-depth]",
            "text": "[trimmed-depth]"
          },
          {
            "type": "[trimmed-depth]",
            "text": "[trimmed-depth]"
          }
        ],
        "multi_buy_offer": null,
        "clearance": false,
        "basket_discounts": [],
        "best_seller": {
          "rank": 1,
          "category": "Yöresel Peynir",
          "text": "Yöresel Peynir kategorisinin en çok satan 1. ürünüdür"
        },
        "rating": null,
        "review_count": null,
        "rating_scale": null,
        "sponsored": false
      },
      {
        "product_id": "10100027",
        "store_product_id": "20000010100027",
        "title": "Tahsildaroğlu Taze Tam Yağlı Dil Peyniri 200 G",
        "brand": {
          "id": 728,
          "name": "Tahsildaroğlu",
          "url": "https://www.migros.com.tr/tahsildaroglu-b-2d8"
        },
        "category": {
          "id": 10046,
          "name": "Yöresel Peynir",
          "url": "https://www.migros.com.tr/yoresel-peynir-c-273e"
        },
        "breadcrumb": [
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          }
        ],
        "url": "https://www.migros.com.tr/tahsildaroglu-taze-tam-yagli-dil-peyniri-200-g-p-9a1d3b",
        "image": "https://images.migrosone.com/sanalmarket/product/10100027/10100027-794c6a-1650x1650.jpg",
        "price": 199.9,
        "price_display": "199,90 TL",
        "currency": "TRY",
        "original_price": null,
        "original_price_display": null,
        "discount_percent": null,
        "member_price": null,
        "member_price_display": null,
        "member_discount_percent": null,
        "member_program": null,
        "unit_price": 999.5,
        "unit_price_unit": "Kg",
        "member_unit_price": null,
        "sold_by": "piece",
        "price_per": "piece",
        "availability": "in_stock",
        "in_stock": true,
        "max_order_quantity": 8,
        "max_order_grams": null,
        "order_step_grams": null,
        "min_order_grams": null,
        "badges": [],
        "multi_buy_offer": null,
        "clearance": false,
        "basket_discounts": [
          "Sepette %20 İndirim"
        ],
        "best_seller": {
          "rank": 2,
          "category": "Yöresel Peynir",
          "text": "Yöresel Peynir kategorisinin en çok satan 2. ürünüdür"
        },
        "rating": null,
        "review_count": null,
        "rating_scale": null,
        "sponsored": false
      },
      {
        "product_id": "10409164",
        "store_product_id": "20000010409164",
        "title": "Bahçıvan Hellim Peyniri 225 G",
        "brand": {
          "id": 729,
          "name": "Bahçıvan",
          "url": "https://www.migros.com.tr/bahcivan-b-2d9"
        },
        "category": {
          "id": 10046,
          "name": "Yöresel Peynir",
          "url": "https://www.migros.com.tr/yoresel-peynir-c-273e"
        },
        "breadcrumb": [
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          },
          {
            "id": "[trimmed-depth]",
            "name": "[trimmed-depth]",
            "url": "[trimmed-depth]"
          }
        ],
        "url": "https://www.migros.com.tr/bahcivan-hellim-peyniri-225-g-p-9ed4cc",
        "image": "https://images.migrosone.com/sanalmarket/product/10409164/10409164-c6d9cc-1650x1650.jpg",
        "price": 259.9,
        "price_display": "259,90 TL",
        "currency": "TRY",
        "original_price": null,
        "original_price_display": null,
        "discount_percent": null,
        "member_price": 149.9,
        "member_price_display": "149,90 TL",
        "member_discount_percent": 42,
        "member_program": "Money",
        "unit_price": 1155.11,
        "unit_price_unit": "Kg",
        "member_unit_price": 666.22,
        "sold_by": "piece",
        "price_per": "piece",
        "availability": "in_stock",
        "in_stock": true,
        "max_order_quantity": 8,
        "max_order_grams": null,
        "order_step_grams": null,
        "min_order_grams": null,
        "badges": [
          {
            "type": "[trimmed-depth]",
            "text": "[trimmed-depth]"
          },
          {
            "type": "[trimmed-depth]",
            "text": "[trimmed-depth]"
          }
        ],
        "multi_buy_offer": null,
        "clearance": false,
        "basket_discounts": [],
        "best_seller": null,
        "rating": null,
        "review_count": null,
        "rating_scale": null,
        "sponsored": false
      }
    ],
    "count": 30,
    "total_results": 454,
    "page": 1,
    "page_count": 16,
    "sponsored_dropped": 6,
    "sort_applied": "relevance",
    "filters_available": {
      "categories": [
        {
          "id": 4,
          "name": "Süt, Kahvaltılık",
          "count": 392
        },
        {
          "id": 70651,
          "name": "Atıştırmalık",
          "count": 36
        },
        {
          "id": 74872,
          "name": "Maç Özel",
          "count": 16
        }
      ],
      "discounts": [
        {
          "id": "money",
          "name": "Money İndirimli Market Ürünleri",
          "count": 74
        },
        {
          "id": "multi_buy",
          "name": "Çoklu İndirim Kampanyaları ve Hediyeli Ürünler",
          "count": 6
        }
      ],
      "brands": [
        {
          "id": 728,
          "name": "Tahsildaroğlu",
          "count": 29
        },
        {
          "id": 729,
          "name": "Bahçıvan",
          "count": 25
        },
        {
          "id": 149,
          "name": "Ariste",
          "count": 20
        }
      ],
      "lifestyle": [
        {
          "id": 113,
          "name": "Glutensiz",
          "count": 5
        },
        {
          "id": 116,
          "name": "Laktozsuz",
          "count": 10
        },
        {
          "id": 102,
          "name": "Organik",
          "count": 6
        }
      ]
    },
    "title": "Arama",
    "breadcrumb": [
      {
        "name": "Arama",
        "url": null
      }
    ],
    "query": "peynir"
  }
}
Actions

What the Migros Sanalmarket API does

ActionDescriptionConcrete use caseKey params
searchSearch migros.com.tr by keyword. Each product comes with its shelf price and, separately, the Money-card member price when Migros runs one, the per-kg or per-litre unit price, availability, campaign badges (multi-buy, clearance, basket discount), brand and category. Sort by price, discount or best sellers, and filter by brand, category, discount type or lifestyle facet. Paid placements are removed unless you ask for them.Pricing teams call search to search migros.com.tr by keyword.query, page, sort, brand_ids, category_ids, ...
product/detailThe full Migros product record by `product_id` (or product URL): title, brand, breadcrumb, every image, the shelf price, the struck-through price and discount, the Money-card member price kept separate, unit price, availability and order limits, campaign badges, the label sheet (ingredients, allergen warning, net quantity, origin, storage and every other labelled line as `specs`), the supplier details Migros is legally required to show, and the store the prices belong to.Marketplace operators call product/detail to get the full Migros product record by `product_id` (or product URL).product_id, max_rotations
product/barcodeLook a product up by the EAN/GTIN barcode on its pack and get the same full record as product/detail — the quickest way to match your own catalogue to Migros prices.Catalog enrichment teams call product/barcode to look a product up by the EAN/GTIN barcode on its pack and get the same full record as product….barcode, max_rotations
dealsMigros's own discount pages: all discounted products, Money-card member discounts, multi-buy campaigns, Migroskop and 'Gördüğünüze İnanın'. Same rows, sorting and filters as search.Retail analysts call deals to get migros's own discount pages.type, page, sort, brand_ids, category_ids, ...
categoryEvery product in one Migros category, paged, with the same rows, sorting and filters as search. Category ids come from `categories`, from search filters or from any row's breadcrumb.Pricing teams call category to get every product in one Migros category, paged, with the same rows, sorting and filters as search.category, page, sort, brand_ids, discount, ...
categoriesMigros Sanalmarket's top-level shelf: every main category with its id and URL, plus the site's campaign pages (mapped to the `deals` type that reads them).Marketplace operators call categories to get migros Sanalmarket's top-level shelf.max_rotations
suggestAutocomplete as a Migros shopper types: suggested search phrases, matching brands and categories, and the top matching products with prices.Catalog enrichment teams call suggest to get autocomplete as a Migros shopper types.query, max_rotations
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/migros/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"peynir"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.migros.search with {"query":"peynir"}.
Use cases

Who uses this API and why

  • Turkish grocery price trackers record price and member_price separately, because the displayed shelf price is the Money-card price whenever a promotion runs.
  • FMCG brands monitor their products' Money discounts, multi-buy offers and clearance flags across Migros categories with deals and category.
  • Retail analysts compare per-kg and per-litre unit prices on a like-for-like non-member basis using unit_price.
  • Catalogue teams match their own EANs to Migros products with product/barcode and pull ingredients, allergen warnings and origin from the label sheet.
FAQ

Questions developers ask before integrating

Which price should I store - price or member_price?

Store both, and label them. price is what a shopper without a Money card pays; member_price is the Money-card price and is null when no Money promotion runs. On 2026-09-15, 12 of 30 sampled products had a member price, and on the Money discount page 30 of 30 rows did - always below price. member_program reads Money whenever member_price is set.

How do I know a member price is really member-only?

Because it lines up with Migros's own list. For the keyword peynir, the 73 products the API flagged with a member price were exactly the 73 products on Migros's Money discount filter - none missing, none extra. On every one of those products checked in full, the regular and non-member prices were equal and only the member price was lower.

Why is unit_price different from the per-kg price on the Migros page?

Because the page calculates it on the member price. Bahçıvan Çeçil Peyniri 200 G prints 749.50 TRY per kg, which is 149.90 divided by 0.2 kg - the Money price. unit_price returns 1,149.75, the per-kg price at the non-member 229.95, and member_unit_price returns the 749.50 the page prints. Products without a Money promotion have one unit price and member_unit_price is null.

Some products are priced per kg - how do I tell?

sold_by reads weight and price_per reads kg. Akpınar Taze Beyaz Peynir Kg is 429.00 TRY per kg, ordered from 1,000 g in 100 g steps up to 8 kg; the order limits come back in grams. Piece-sold products read sold_by piece, and max_order_quantity is Migros's order cap - 8 on most products - not a stock count.

Do filters and sorting really apply?

Yes, and Migros confirms the sort it used in sort_applied. Measured on 2026-09-15 for peynir: 451 results unfiltered, 55 with two brand ids, 73 with the Money discount filter, 35 with one category id, 10 with the lactose-free lifestyle facet. Price sorts came back in order on page 2. Migros places sponsored products on the first page regardless of your filters and sort, so they are removed by default and counted in sponsored_dropped; include_sponsored=true keeps them, flagged.

Can I look a product up by barcode?

Yes. product/barcode takes the EAN on the pack and returns the same full record as product/detail - the Coca-Cola 1.5 L EAN 5449000000439 resolved to Migros product 08010903 at 80.00 TRY. An unknown barcode returns NOT_FOUND. Migros does not print the barcode inside the product record itself, so product/detail returns barcode as null.

Which campaign pages can I read?

deals reads Migros's own discount pages: all discounted products (3,157 on 2026-09-15), Money-card discounts (2,100), multi-buy and gift campaigns (363, each row carrying its offer text such as 2.si %80), Migroskop (2,467) and Gördüğünüze İnanın, which was empty between campaigns that day and returns an honest empty list. Rows, sorting and filters are the same as search.

What does Migros NOT publish?

Product ratings and reviews - there are none, so rating, review_count and rating_scale are null. No stock count, only availability. No structured nutrition table: in 30 sampled products the label information came as labelled lines, returned in specs. Label sheets are missing on some non-food categories (baby, produce, paper, some cosmetics and cleaning products), so description and specs are null there. Prices are those of Migros's default online store for a visitor with no delivery address; prices for a specific delivery address are not offered.

What is the Migros Sanalmarket API?

Migros Sanalmarket API is a ReefAPI endpoint group for turkish online grocery: shelf prices, money-card member prices and full label sheets. It returns live JSON through POST requests under /migros/v1.

Is the Migros Sanalmarket API free to try?

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

Do I need a Migros Sanalmarket login or account?

No login to Migros Sanalmarket 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 Migros Sanalmarket 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 Migros Sanalmarket API use?

Migros Sanalmarket actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Migros Sanalmarket from an AI assistant or MCP client?

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

docs / migros

Migros Sanalmarket

Turkish online grocery: shelf prices, Money-card member prices and full label sheets.

base /migros/v17 endpoints
post/migros/v1/product/detail1 credit

The full Migros product record by `product_id` (or product URL): title, brand, breadcrumb, every image, the shelf price, the struck-through price and discount, the Money-card member price kept separate, unit price, availability and order limits, campaign badges, the label sheet (ingredients, allergen warning, net quantity, origin, storage and every other labelled line as `specs`), the supplier details Migros is legally required to show, and the store the prices belong to.

ParameterAllowed / rangeDescription
product_idrequiredMigros product id (the 8-digit sku every search row returns as `product_id`, leading zeros included), or a migros.com.tr product URL.
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →
post/migros/v1/product/barcode1 credit

Look a product up by the EAN/GTIN barcode on its pack and get the same full record as product/detail — the quickest way to match your own catalogue to Migros prices.

ParameterAllowed / rangeDescription
barcoderequiredThe product's EAN/GTIN barcode as printed on the pack (8-14 digits).
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →
post/migros/v1/deals1 credit

Migros's own discount pages: all discounted products, Money-card member discounts, multi-buy campaigns, Migroskop and 'Gördüğünüze İnanın'. Same rows, sorting and filters as search.

ParameterAllowed / rangeDescription
type = alloptionalall · money · multi_buy · migroskop · gordugunuze_inaninWhich of migros.com.tr's own campaign pages to read.
page = 1optional1–500Result page, 1-based. Migros returns about 30 products per page; read `count`, `total_results` and `page_count` rather than assuming a size.
sort = relevanceoptionalrelevance · best_selling · price_asc · price_desc · discount_percent · discount_amountResult order. Only orderings migros.com.tr honours without an account; `sort_applied` in the response is Migros's own confirmation.
brand_idsoptionalOnly these brands (Migros brand ids — every result row and `filters_available.brands` carries them). Several ids are OR-ed.
category_idsoptionalOnly these categories (ids from `filters_available.categories` or a row's `category.id` / `breadcrumb[].id`). Several ids are OR-ed.
include_sponsored = falseoptionalfalse (default) drops paid placements. Migros injects them on the first page regardless of your filters and sort, so they would break both; true keeps them, flagged `sponsored: true`.
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →
post/migros/v1/category1 credit

Every product in one Migros category, paged, with the same rows, sorting and filters as search. Category ids come from `categories`, from search filters or from any row's breadcrumb.

ParameterAllowed / rangeDescription
categoryrequiredA category: its Migros id (from `categories`, a row's `breadcrumb[].id` or `filters_available.categories`), its slug ('peynir-c-6d') or its migros.com.tr URL.
page = 1optional1–500Result page, 1-based. Migros returns about 30 products per page; read `count`, `total_results` and `page_count` rather than assuming a size.
sort = relevanceoptionalrelevance · best_selling · price_asc · price_desc · discount_percent · discount_amountResult order. Only orderings migros.com.tr honours without an account; `sort_applied` in the response is Migros's own confirmation.
brand_idsoptionalOnly these brands (Migros brand ids — every result row and `filters_available.brands` carries them). Several ids are OR-ed.
discountoptionalmoney · multi_buyOnly discounted products of this kind.
lifestyle_idsoptionalLifestyle/diet facets (e.g. gluten-free, lactose-free, organic, vegan) — ids from `filters_available.lifestyle`.
include_sponsored = falseoptionalfalse (default) drops paid placements. Migros injects them on the first page regardless of your filters and sort, so they would break both; true keeps them, flagged `sponsored: true`.
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →
post/migros/v1/categories1 credit

Migros Sanalmarket's top-level shelf: every main category with its id and URL, plus the site's campaign pages (mapped to the `deals` type that reads them).

ParameterAllowed / rangeDescription
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →
post/migros/v1/suggest1 credit

Autocomplete as a Migros shopper types: suggested search phrases, matching brands and categories, and the top matching products with prices.

ParameterAllowed / rangeDescription
queryrequiredWhat to look for, as a shopper would type it on migros.com.tr. Turkish keywords match best ('peynir', 'zeytinyağı', 'bebek bezi'); brand names work too.
max_rotations = 3optional1–6Advanced: how many times to retry a difficult request (1-6, default 3).
Try in playground →