Документация парсера WB (Wildberries)

Парсер WB (Wildberries, Вайлдберриз) через API BHAPI возвращает карточки товаров, цены, изображения, характеристики и результаты поиска в JSON. Здесь описаны методы получения карточки, поиска товаров, каталога продавца и обзора отзывов, параметры запросов, формат ответов и примеры кода.

Парсер WB: возможности и подключение

WB: получить товар по URL

GET /wb/api/v1/item/by-url

Парсит один товар Wildberries по URL и возвращает JSON с описанием, размерами, остатками, ценами, доставкой и таблицей замеров, если она предоставлена.

Параметры запроса

ПараметрТипОбязательныйОписание
url string да URL детальной карточки WB: https://www.wildberries.ru/catalog/<nm_id>/detail.aspx.
pickup_point_idintegerнетКод ПВЗ из справочника, больше 0 и меньше 2**63.

Заголовки

ЗаголовокОбязательныйОписание
X-API-Token да Ваш API‑токен портала. Передавайте только в заголовке.

Пример запроса

cURL
curl -X GET \
  "https://bhapi.ru/wb/api/v1/item/by-url?url=https://www.wildberries.ru/catalog/12345/detail.aspx" \
  -H "X-API-Token: ВАШ_API_TOKEN"

Успешный ответ 200 OK

Учебный пример с двумя размерами: первый недоступен, второй имеет остаток 3. Данные товара находятся в data.data. Описание полей — в разделе «Карточка товара». Те же поля возвращает POST /wb/api/v1/parse/single с JSON-телом {"url":"https://www.wildberries.ru/catalog/267995621/detail.aspx"}.

JSON
{
  "status": "ok",
  "data": {
    "code": 200,
    "msg": "success",
    "data": {
      "item_id": 267995621,
      "product_url": "https://www.wildberries.ru/catalog/267995621/detail.aspx",
      "title": "Брюки домашние в клетку хлопок пижамные",
      "currency": "RUB",
      "price_info": {
        "sale_price": null,
        "pre_sale_price": 1311.0,
        "origin_price": 3100.0,
        "debug": {
          "saleConditions": 134217728
        }
      },
      "delivery_info": {
        "cost": 0.0,
        "currency": "RUB",
        "time1_hours": 3,
        "time2_hours": 20,
        "estimated_hours": 23,
        "estimated_days": 1
      },
      "main_imgs": [],
      "additional_imgs": [],
      "complectation": "",
      "category_name": "",
      "category_path": "",
      "product_props": {},
      "shop_info": {
        "shop_name": "",
        "shop_id": "",
        "seller_id": ""
      },
      "review_info": {
        "rating_star": 0.0,
        "review_count": 0
      },
      "desc": "",
      "source": "wildberries",
      "availability": 3,
      "availability_status": "in_stock",
      "price_size_option_id": 415163657,
      "sizes": [
        {
          "name": "46_182",
          "orig_name": "46_182",
          "option_id": 415163656,
          "availability": 0,
          "availability_status": "out_of_stock",
          "price_info": {
            "sale_price": null,
            "pre_sale_price": null,
            "origin_price": null
          },
          "delivery_info": {
            "cost": null,
            "currency": "RUB",
            "time1_hours": null,
            "time2_hours": null,
            "estimated_hours": null,
            "estimated_days": null
          },
          "stocks": []
        },
        {
          "name": "48_182",
          "orig_name": "48_182",
          "option_id": 415163657,
          "availability": 3,
          "availability_status": "in_stock",
          "price_info": {
            "sale_price": null,
            "pre_sale_price": 1311.0,
            "origin_price": 3100.0,
            "debug": {
              "saleConditions": 134217728
            }
          },
          "delivery_info": {
            "cost": 0.0,
            "currency": "RUB",
            "time1_hours": 3,
            "time2_hours": 20,
            "estimated_hours": 23,
            "estimated_days": 1
          },
          "stocks": [
            {
              "warehouse_id": 6310768265,
              "quantity": 3,
              "delivery_info": {
                "cost": null,
                "currency": "RUB",
                "time1_hours": 3,
                "time2_hours": 20,
                "estimated_hours": 23,
                "estimated_days": 1
              }
            }
          ]
        }
      ],
      "sizes_table": {
        "details_props": [
          "RU",
          "Длина внутреннего шва, в см",
          "Длина внешнего шва, в см",
          "Обхват бедер, в см"
        ],
        "values": [
          {
            "tech_size": "46_182",
            "chrt_id": 415163656,
            "details": [
              "46_182",
              "74",
              "106",
              "104"
            ]
          },
          {
            "tech_size": "48_182",
            "chrt_id": 415163657,
            "details": [
              "48_182",
              "74",
              "106",
              "108"
            ]
          }
        ]
      },
      "data_quality": {
        "is_partial": false,
        "missing_fields": []
      },
      "data_freshness": {
        "assembled_at": "2026-10-22T07:59:44.491696+00:00",
        "cache_hit": false,
        "cache_age_seconds": 0,
        "cache_ttl_seconds": 300,
        "dest": -5818883
      }
    }
  },
  "saved_path": null
}

WB: поиск похожих товаров по изображению

POST /wb/api/v1/search/image

Загрузите одну фотографию товара, чтобы получить упорядоченный список похожих карточек Wildberries. Успешный вызов расходует 1 успешный запрос WB; ошибки валидации и внешнего сервиса не считаются успешным расходом квоты.

Поля формы

ПолеТипОбязательноеОписание
image file да Изображение JPEG, PNG или WebP размером до 10 МБ. MIME-тип должен соответствовать содержимому файла.
max_results integer нет Число результатов от 1 до 256; по умолчанию 100.
label string нет Необязательная метка до 64 символов. Пустое значение игнорируется.
pickup_point_idintegerнетПоле multipart-формы: код ПВЗ из справочника.
Важно. Не задавайте общий заголовок Content-Type: multipart/form-data вручную: HTTP-клиент сам сформирует multipart boundary для поля файла.

Пример запроса

cURL
curl -X POST "https://bhapi.ru/wb/api/v1/search/image" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -F "image=@product.png;type=image/png" \
  -F "max_results=10"

Успешный ответ 200 OK

JSON
{
  "status": "ok",
  "data": {
    "count": 2,
    "label": null,
    "engine": "siglip2_mrl_crop",
    "search_engine": "qdrant",
    "nm_ids": [123456789, 987654321],
    "links": [
      "https://www.wildberries.ru/catalog/123456789/detail.aspx",
      "https://www.wildberries.ru/catalog/987654321/detail.aspx"
    ]
  }
}

Поля nm_ids и links идут в одном порядке; count равно числу элементов в обоих массивах.

WB: метаданные пресетов категорий

GET /wb/api/v1/search/presets

Возвращает стабильные имена полей для трёх готовых пресетов: обувь (footwear), одежда (clothing) и головные уборы (headwear). Список не означает, что пресет подготовлен для каждой категории WB.

Пример запроса

cURL
curl -X GET "https://bhapi.ru/wb/api/v1/search/presets" \
  -H "X-API-Token: ВАШ_API_TOKEN"

Структура ответа

ПолеТипОписание
data.presets[].namestringИмя для поля preset.
data.presets[].labelstringРусское название категории.
data.presets[].fields[].namestringИмя поля для preset_filters.
data.presets[].fields[].labelstringПонятное название поля.
data.presets[].fields[].multiplebooleanМожно ли передать несколько значений.
Квота: метаданные пресетов расходуют 0 запросов. Нужен действующий токен WB, но поиск товаров не запускается.

WB: динамические фильтры запроса

POST /wb/api/v1/search/filters

Возвращает актуальные группы характеристик и допустимые значения для конкретного поискового запроса. Фильтры зависят от запроса, региона и времени; полученный ID не следует считать постоянным глобальным словарём.

Тело запроса

ПолеТипОбязательныйОписание
querystringдаТовар или категория для исследования.
characteristic_filtersobjectнетУже выбранные ID для контекстного уточнения списка.
pickup_point_idintegerнетКод ПВЗ. Передайте тот же ПВЗ в последующем поиске, чтобы фильтры соответствовали региону.

Пример cURL

cURL
curl -X POST "https://bhapi.ru/wb/api/v1/search/filters" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{"query":"лыжи классические"}'

Пример Python

Python — requests
import requests

response = requests.post(
    "https://bhapi.ru/wb/api/v1/search/filters",
    json={"query": "лыжи классические"},
    headers={"X-API-Token": "ВАШ_API_TOKEN"},
    timeout=210,
)
response.raise_for_status()
for group in response.json()["data"]["filters"]:
    print(group["key"], group["name"], group["values"])

Таймаут клиента должен быть больше фактического таймаута reverse proxy. В примере оставлен запас над рекомендуемыми 180 секундами.

Структура ответа

ПолеТипОписание
data.querystringИсходный поисковый запрос.
data.totalintegerЧисло товаров в текущем контексте.
data.filters[].keystringКлюч группы WB; поле итогового поиска выбирается по таблице ниже.
data.filters[].values[].idintegerSigned ID; отрицательный знак копируется без изменения.
data.filters[].values[].namestringОтображаемое значение.
data.filters[].values[].countinteger | nullДоступное число товаров, если оно известно.

Как перенести группу в поиск

Не переносите все группы механически в characteristic_filters. Используйте назначение по ключу или типу группы.

Группа discoveryПоле поискаПравило
Только ключи вида f<цифры>characteristic_filtersСохраните ключ и signed ID без изменения.
fbrandbrand_idsПередайте выбранные ID брендов массивом.
Цена / базовая цена (priceU)min_price, max_priceПередайте границы в рублях, а не ID значений группы.
faction / распродажаsale_type: trueПоддерживается только значение «Распродажа» с ID 1024637.
Другое значение faction или иная служебная группа не поддерживается публичным поиском. Не переписывайте такой ключ в characteristic_filters: используйте документированное поле, пресет или пропустите группу.
Успешный discovery расходует 1 успешный запрос. Последующий успешный поиск расходует ещё один, поэтому двухшаговый flow — 2 успешных запроса.

Сценарии дополнительных фильтров

Значения внутри одного массива объединяются как OR внутри одной группы, а разные ключи — как AND между группами. Пресеты и raw-ID можно сочетать с ценой, распродажей и brand_ids в одном POST-поиске.

Обувь: коричневые мужские лоферы, размер 45

cURL — footwear
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{
    "query":"лоферы мужские",
    "page":1,
    "preset":"footwear",
    "preset_filters":{
      "color":["коричневый"],
      "size":["45"],
      "gender":["мужской"]
    }
  }'

Для raw-ID сценария тот же коричневый цвет задаётся как "characteristic_filters":{"f1000000888":[-1000025867]}. Отрицательный знак сохраняется; raw-ID и пресет можно объединять.

Одежда: женская футболка, размер 46, оверсайз

cURL — clothing
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{
    "query":"футболка женская",
    "preset":"clothing",
    "preset_filters":{
      "size":["46"],
      "fit":["оверсайз"],
      "gender":["женский"]
    }
  }'

Головные уборы: женская шапка, размер 56

Python — headwear
import requests

payload = {
    "query": "шапка женская",
    "preset": "headwear",
    "preset_filters": {"size": ["56"], "gender": ["женский"]},
}
response = requests.post(
    "https://bhapi.ru/wb/api/v1/search",
    json=payload,
    headers={"X-API-Token": "ВАШ_API_TOKEN"},
    timeout=210,
)
response.raise_for_status()

Произвольная категория: классические лыжи

Сначала выполните discovery с {"query":"лыжи классические"}, затем скопируйте выбранные signed ID без изменения в канонический POST-поиск:

cURL — characteristic_filters
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{
    "query":"лыжи классические",
    "characteristic_filters":{
      "f1000000896":[-1000041358],
      "f13649":[143021],
      "f121981":[121983]
    }
  }'
Один успешный вызов POST /wb/api/v1/search, в том числе с пресетом, расходует 1 успешный запрос.

WB: каталог продавца по ссылке

POST /wb/api/v1/seller/catalog

Возвращает каталог товаров конкретного продавца Wildberries по ссылке на магазин /seller/<id>.

Тело запроса

ПолеТипОбязательныйОписание
url string да URL продавца WB: https://www.wildberries.ru/seller/<supplier_id>.
page integer нет Номер страницы каталога продавца, по умолчанию 1.
pickup_point_idintegerнетКод ПВЗ из справочника.

Заголовки

ЗаголовокОбязательныйОписание
X-API-Token да Ваш API‑токен портала. Передавайте только в заголовке.

Пример запроса

cURL
curl -X POST "https://bhapi.ru/wb/api/v1/seller/catalog" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{"url":"https://www.wildberries.ru/seller/4190071","page":1}'

Успешный ответ 200 OK

JSON
{
  "status": "ok",
  "data": {
    "code": 200,
    "msg": "success",
    "data": {
      "supplier_id": 4190071,
      "page": 3,
      "products_count": 100,
      "per_page": 100,
      "max_pages": 5,
      "total": 490,
      "wb": {
        "products": [
          {
            "id": 277304775,
            "name": "Мотор насос омывателя 2101-2107 2121"
          }
        ]
      }
    }
  }
}

WB: теги и статистика отзывов по imt_id

POST /wb/api/v1/item/review_scope

Возвращает сводку сильных и слабых сторон товара по отзывам WB, статистику оценок и ссылки на пользовательские фото. Публичный путь BHAPI для этого сценария: review_scope.

Тело запроса

ПолеТипОбязательныйОписание
imt_id integer да WB imtId товара из feedbacks/tags API. Это не всегда то же самое, что nm_id карточки.
lang string нет Язык ответа, по умолчанию ru.

Заголовки

ЗаголовокОбязательныйОписание
X-API-Token да Ваш API‑токен портала. Передавайте только в заголовке.

Пример запроса

cURL
curl -X POST "https://bhapi.ru/wb/api/v1/item/review_scope" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{"imt_id":733309467,"lang":"ru"}'

Успешный ответ 200 OK

JSON
{
  "status": "ok",
  "data": {
    "code": 200,
    "msg": "success",
    "data": {
      "imt_id": 733309467,
      "lang": "ru",
      "summary": [
        { "tag_id": 8, "name": "Качество", "plus_count": 47, "minus_count": 0 }
      ],
      "items": [
        { "nm_id": 537724276, "summary": [] }
      ],
      "valuation": 4.8,
      "valuationSum": 55350,
      "valuationDistribution": { "1": 193, "2": 71, "3": 137, "4": 461, "5": 10552 },
      "nmValuationDistribution": [],
      "feedbackCount": 1036,
      "photo_links": [
        "https://feedback-01.wbbasket.ru/example/ms.webp"
      ],
      "wb": {
        "summary": [ ],
        "items": [ ]
      }
    }
  },
  "saved_path": null
}

Ключевые поля ответа

ПолеОписание
summaryОбщие теги отзывов по товару: название тега, tag_id, количество плюсов и минусов.
itemsДетализация тегов по конкретным nm_id, если WB вернул такую разбивку.
valuation, valuationSumСредняя оценка и суммарное количество оценок.
valuationDistributionРаспределение оценок от 1 до 5.
nmValuationDistributionРаспределение оценок по отдельным nm_id.
photo_linksГотовые URL пользовательских фото из отзывов.
wbСырой ответ WB по тегам отзывов.

WB: пункты выдачи и доставка

GET /wb/api/v1/pickup-points

Возвращает справочник пунктов выдачи Wildberries. Используйте его, чтобы выбрать ПВЗ для получения цен, доступности товаров и данных доставки.

Параметры запроса

ПараметрТипОбязательныйОписание
querystringнетПоиск по части адреса без учёта регистра или точному коду ПВЗ. До 256 символов. Без параметра возвращается страница всего справочника.
limitintegerнетРазмер страницы: от 1 до 200, по умолчанию 50.
offsetintegerнетСмещение: от 0 до 250000, по умолчанию 0. Для следующей страницы увеличивайте на limit.

Заголовки

ЗаголовокОбязательныйОписание
X-API-TokenдаВаш API-токен портала. Передавайте только в заголовке.
Квота. Чтение справочника и отдельного ПВЗ не расходует квоту успешного парсинга. Действует общее ограничение частоты запросов.

Пример запроса

cURL
curl --get "https://bhapi.ru/wb/api/v1/pickup-points" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  --data-urlencode "query=Москва" \
  --data-urlencode "limit=10" \
  --data-urlencode "offset=0"

Успешный ответ 200 OK

Данные примера условные. Используйте data.items[].id для выбора ПВЗ.

JSON
{
  "status": "ok",
  "data": {
    "total": 1,
    "count": 1,
    "items": [
      {
        "id": 123,
        "dest": -1234,
        "address": "Москва, пример адреса"
      }
    ]
  }
}

Ключевые поля ответа

ПолеТипОписание
data.totalintegerЧисло совпадений до пагинации.
data.countintegerКоличество ПВЗ на текущей странице.
data.itemsarrayПункты выдачи: id — код ПВЗ, address — адрес, dest — региональный код доставки, который сервис определяет сам.
data.items[].countrystringСтрана, если она присутствует в справочнике.
data.items[].coordinatesarrayКоординаты [широта, долгота], если они доступны.

ПВЗ по идентификатору

GET /wb/api/v1/pickup-points/{pickup_point_id}

Возвращает один пункт выдачи непосредственно в data. Требуется тот же заголовок X-API-Token.

Параметр путиТипОбязательныйОписание
pickup_point_idintegerдаКод из data.items[].id, больше 0 и меньше 2**63.

Пример запроса

cURL
curl "https://bhapi.ru/wb/api/v1/pickup-points/123" \
  -H "X-API-Token: ВАШ_API_TOKEN"

Успешный ответ 200 OK

JSON
{
  "status": "ok",
  "data": {
    "id": 123,
    "dest": -1234,
    "address": "Москва, пример адреса"
  }
}

Выбор ПВЗ для запросов товаров

Передайте код из справочника как необязательный pickup_point_id — положительное целое число меньше 2**63. Все пути в таблице имеют префикс /wb/api/v1.

МетодГде передавать
GET item/by-url, searchQuery-параметр.
POST parse/single, search, search/filters, seller/catalogПоле JSON.
POST search/imageПоле multipart-формы.

В JSON строки, дроби и логические значения отклоняются. Без параметра сохраняется прежнее поведение. Для отзывов и статических пресетов параметр не используется.

cURL · поиск с выбранным ПВЗ
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"кроссовки","pickup_point_id":123}'

Замените условный 123 идентификатором из справочника.

Данные доставки

delivery_context подтверждает выбранные pickup_point_id, dest и address. Расположение полей зависит от метода:

МетодКонтекст ПВЗДанные доставки
item/by-url, parse/singledata.data.delivery_contextdata.data.delivery_info
search, search/imagedata.delivery_contextdata.products[].delivery_info
seller/catalogdata.data.delivery_contextdata.data.products[].delivery_info
search/filtersdata.delivery_contextНе возвращает товары.
Поле delivery_infoОписание
cost, currencyСтоимость доставки в рублях, currency: "RUB". Не прибавляется к цене товара. 0 — известная нулевая стоимость, null — неизвестная.
time1_hours, time2_hoursСоставляющие срока в часах. Недоступные значения могут быть null.
estimated_hoursСумма time1_hours и time2_hours, если известны обе величины.
estimated_daysОкруглённая вверх длительность: ceil(estimated_hours / 24). Это оценка в сутках, а не гарантированная календарная дата WB.

Стоимость, доступность и сроки зависят от товара, выбранного ПВЗ и актуального ответа WB.

Ошибки

Код APIHTTP-статусЧто делать
pickup_point_not_found404Выберите другой ПВЗ из справочника.
pickup_point_catalog_unavailable503Повторите запрос позже: справочник временно недоступен.

Для 503 поле detail.reason_type уточняет причину: pickup_point_catalog_timeout, pickup_point_catalog_network, pickup_point_catalog_protocol или pickup_point_catalog_upstream. Для 404 причина — pickup_point_not_found.

Эти ошибки применяются к справочнику и товарным запросам. Если явно выбранный ПВЗ недоступен, сервис возвращает ошибку и не подменяет его регионом по умолчанию. Неуспешные запросы не расходуют квоту успешного парсинга. Общий формат отказов описан в разделе «Коды ошибок».

Обёртка ответа парсера WB

Ответы WB API в BHAPI возвращаются в единой обёртке: статус, полезная нагрузка и путь сохранения, если он был запрошен.

ПолеТипОписание
status string Статус верхнего уровня портала: обычно "ok" или "error".
data object Полезная нагрузка. Для одиночного товара содержит поля code, msg, data.
saved_path string | null Поле совместимости; публичный BHAPI не сохраняет ответы на сервере и возвращает null.

Во внутреннем объекте data для одиночного товара структура такая:

ПолеТипОписание
codeintegerКод обработки запроса: 200 — успешный результат; остальные значения обозначают ошибку.
msgstringТекстовое описание результата ("success" или сообщение об ошибке).
dataobjectКарточка товара WB (см. раздел «Карточка товара» ниже).

Карточка товара WB

Полная карточка находится в data.data ответа на GET /wb/api/v1/item/by-url и POST /wb/api/v1/parse/single. Массивы размеров и замеры не добавляются в краткие результаты поиска, поиска по изображению и каталога продавца. Схемы клиентов должны допускать новые поля ответа.

ПолеТипОписание
item_idintegerИдентификатор товара WB (nm_id).
product_urlstringURL детальной карточки товара.
titlestringНазвание товара.
currencystringКод валюты, как правило RUB.
price_infoobjectСводные цены одного варианта в рублях; правила выбора и значения полей описаны ниже.
main_imgsstring[]Массив URL основных изображений товара.
additional_imgsstring[]Дополнительные изображения (если есть).
complectationstringКомплектация из карточки товара.
category_namestringНазвание категории.
category_pathstringПуть до категории (цепочка разделов).
product_propsobjectСловарь характеристик «название → значение» (объём памяти, цвет, ОС и т.п.).
shop_infoobjectИнформация о продавце (см. ниже).
review_infoobjectИнформация по отзывам (может быть пустым объектом).
descstringТекстовое описание товара.
sourcestringИсточник данных, обычно "wildberries".
availabilityinteger | stringСумма известных остатков всех размеров; 0 — известный ноль, "unknown" — итог неизвестен. Тип со строкой сохранён для совместимости.
availability_statusstringin_stock, out_of_stock или unknown. Проверяйте это поле явно, без преобразования строки в boolean.
price_size_option_idinteger | nullID варианта, из которого выбрана сводная цена.
delivery_infoobjectСводная доставка: сроки товара и стоимость варианта сводной цены.
delivery_contextobjectКонтекст явно выбранного ПВЗ: ID, адрес и регион; см. «ПВЗ и доставка».
sizesobject[]Варианты одного артикула с собственной ценой, наличием, доставкой и складами.
sizes_tableobject | nullТаблица замеров продавца; null, если не предоставлена или не распознана.
data_qualityobjectПризнак частичных данных и пути недостающих полей.
data_freshnessobjectВремя сборки, возраст кэша и применённый регион.

Размеры и складские остатки

sizes содержит варианты одного item_id, а не другие цвета с отдельными артикулами. Порядок массива следует ответу WB и может меняться. Для связи используйте ID варианта.

Поле sizes[]ТипОписание
option_idinteger | nullID варианта WB; связывает размер с замерами. Это не штрихкод и не артикул продавца.
name, orig_namestring | nullНазвание размера WB и исходное название производителя. Могут различаться; форматы 50/194, 50-194, 48_182 сохраняются.
availabilityinteger | nullСумма известных остатков размера: 0 — нет в наличии, null — неизвестно.
availability_statusstringin_stock, out_of_stock, unknown.
price_infoobjectЦена этого размера в рублях.
delivery_infoobjectДоставка этого размера без заимствования сроков из сводки товара.
stocksobject[]Складские записи: warehouse_id (integer | null), quantity (integer | null), собственный delivery_info. ID склада не раскрывает его название или адрес.

Известный пустой список складов означает нулевой остаток в данном ответе и регионе. Отсутствующие или некорректные исходные остатки означают неизвестность. Если неизвестно хотя бы одно слагаемое, итог размера неизвестен; неизвестный размер делает неизвестным общий итог товара. Остаток не является резервом и не гарантирует доступное для заказа количество.

Цены и выбор сводного варианта

Поле price_infoТипОписание
pre_sale_pricenumber | nullЦена товара в рублях, полученная делением исходного значения WB на 100. В проверенных карточках — без дополнительной скидки Кошелька.
origin_pricenumber | nullБазовая цена в рублях, обычно зачёркнутая на сайте.
sale_pricenumber | nullПоле совместимости; сейчас null, цена с условной скидкой не вычисляется.
debug.saleConditionsinteger, необязательноИсходное число WB, не готовый процент скидки.

Сводка выбирает первый в порядке WB размер с pre_sale_price и известным положительным остатком; если такого нет — первый с этой ценой. Если pre_sale_price нет ни у одного размера, то же правило применяется к origin_price. Все поля сводной цены относятся к одному варианту, указанному в price_size_option_id. Это не минимум по размерам и не выбор размера в браузере.

При отсутствии цены размера возможна цена первой складской записи того же размера; поля разных цен не смешиваются. null означает неизвестную цену, а не ноль. Нулевая цена возвращается только при корректном нуле в источнике.

Наличие цены не доказывает возможность покупки. Для выбранного размера берите цену, наличие и доставку из одного элемента sizes. Параметр выбора option_id в запросе не предусмотрен. Скидка WB Кошелька, персональные скидки, WB Клуб и банковские акции не гарантируются; итоговая цена оформления может отличаться.

Доставка размера и склада

На каждом уровне delivery_info содержит cost, currency, time1_hours, time2_hours, estimated_hours, estimated_days. Бесплатная известная доставка — cost=0, неизвестная — null. Стоимость доставки не прибавляется к цене товара.

estimated_hours = time1_hours + time2_hours, если известны оба компонента; estimated_days = ceil(estimated_hours / 24). Это длительность, а не гарантированная календарная дата. Доставка склада не наследует сроки размера или товара; складская стоимость может быть неизвестна при известной стоимости размера.

Регион влияет на цену, остаток и доставку. Передавайте pickup_point_id из справочника ПВЗ; при смене ПВЗ запросите карточку заново. Без ПВЗ используется регион сервиса, который может отличаться от региона браузера. Передавать dest вручную не требуется.

Таблица замеров

Поле sizes_tableТипОписание
details_propsstring[]Названия колонок в исходном порядке WB; состав зависит от продавца.
valuesobject[]Строки замеров со следующими полями.
tech_sizestring | nullИсходный размер производителя, отдельно от значений колонок.
chrt_idintegerID для связи с sizes[].option_id.
detailsstring[]Значения строки в порядке details_props.

Связывайте строки по sizes[].option_id == sizes_table.values[].chrt_id, а не по позиции или названию. tech_size не добавляется в начало details. Метка RU обозначает колонку российского размера. Колонки не ограничены ростом, талией и бёдрами. Таблица может содержать меньше строк, чем вариантов; отсутствие строки не означает отсутствия товара.

Качество и свежесть данных

ОбъектПолеТип и значение
data_qualityis_partialboolean — обнаружены недоступные или некорректные проверяемые данные.
data_qualitymissing_fieldsstring[] — пути, например sizes[1].stocks, sizes[1].price_info.pre_sale_price, sizes.truncated.
data_freshnessassembled_atstring — UTC ISO 8601, время первоначальной сборки карточки; сохраняется при ответе из кэша.
data_freshnesscache_hitboolean — ответ получен из кэша парсера.
data_freshnesscache_age_secondsnumber — возраст записи кэша, 0 для нового ответа.
data_freshnesscache_ttl_secondsinteger — настроенный срок хранения записи кэша.
data_freshnessdestinteger — применённый регион, в том числе без явного ПВЗ.

После проверки status и data.code проверяйте data_quality. Успешная карточка может быть частичной. Без явного ПВЗ недоступность источника динамических данных может дать is_partial=true; с явным ПВЗ непригодный региональный ответ возвращает ошибку. Явная ошибка WB не превращается в успешную частичную карточку.

is_partial=false не гарантирует каждое необязательное поле: таблица или строка замеров может отсутствовать, у недоступного размера допустимы неизвестные цена и доставка. Проверка полноты не охватывает складскую стоимость, рейтинг, фотографии и персональные цены. Пустой sizes или отсутствие цены сами по себе не означают отсутствие товара; проверяйте availability_status.

Ограничения ответа: 200 вариантов, 100 складских записей на вариант, 200 строк замеров и 32 колонки. Усечение отмечается в missing_fields; усечённый список не выдаётся за полный остаток. Пагинации этих массивов нет.

assembled_at — не время изменения товара у WB, а возраст кэша относится только к записи парсера, без оценки кэша WB/CDN. Источники карточки загружаются отдельно и не образуют атомарный снимок. Частичный ответ также может быть получен из кэша.

ShopInfo — информация о продавце

ПолеТипОписание
shop_namestringОтображаемое название магазина (может быть пустой строкой).
shop_idstringИдентификатор магазина WB.
seller_idstringИдентификатор продавца (может совпадать с shop_id).

Структура результата поиска

Объект data в ответе на /wb/api/v1/search детализированно описан ниже.

ПолеТипОписание
querystringИсходный поисковый запрос.
pageintegerНомер текущей страницы.
totalintegerОбщее число найденных товаров по всем страницам.
linksstring[]Массив URL карточек товаров на текущей странице.
countintegerКоличество элементов в массиве links.
productsobject[]Массив кратких описаний товаров.

Элемент products[i]

ПолеТипОписание
idintegernm_id товара WB.
linkstringURL детальной карточки товара.
pricefloat | nullТекущая цена в рублях (может быть null).
ratingfloat | nullРейтинг по отзывам.
feedbacksinteger | nullКоличество отзывов/оценок.
descriptionstring | nullКраткое текстовое описание товара.

Коды ошибок

Таблицы и примеры этого раздела описывают ошибки legacy (формат по умолчанию). Чтобы получать единый контракт ошибок, передайте заголовок X-BHAPI-Error-Format: problem-v1. Статусы некоторых ошибок в этом режиме отличаются; успешные ответы не меняются. Общий справочник кодов, форматов и действий клиента →

Типичные коды ошибок при работе с парсером WB через портал BHAPI:

Код APIHTTP-статусОписаниеЧто делать
pickup_point_not_found404ПВЗ не найден или не имеет доступного региона доставки.Выберите другой id из справочника.
pickup_point_catalog_unavailable503Справочник ПВЗ временно недоступен.Повторите запрос позже.
— 401 Токен не передан или невалиден. Проверьте заголовок X-API-Token, при необходимости создайте новый токен.
— 403 Токен деактивирован, Free WB завершён или платная подписка WB не действует. Проверьте тарифы и статус токена в личном кабинете.
— 404 Товар не найден (удалён, скрыт или неверный URL). Убедитесь, что URL ведёт на существующую карточку WB и содержит корректный nm_id.
— 422 Ошибка валидации параметров запроса. Проверьте обязательные параметры (url или query), числовые фильтры и формат значений.
preset_field_unknown 422 Поле отсутствует в выбранном пресете. Получите текущий список полей через GET /wb/api/v1/search/presets.
preset_filter_value_unavailable 422 Запрошенное friendly-значение сейчас недоступно. Выберите другое значение или используйте динамический discovery.
search_filters_timeout 502 Получение актуальных фильтров не уложилось в срок. Повторите запрос позднее; операция не считается успешным расходом квоты.
image_empty 400 В поле image передан пустой файл. Выберите непустой файл JPEG, PNG или WebP.
image_too_large 413 Размер загружаемого изображения превышает 10 МБ. Уменьшите размер файла и повторите запрос.
image_type_invalid 415 MIME-тип не поддерживается или не совпадает с содержимым файла. Передайте JPEG, PNG или WebP с корректным type в поле формы.
image_label_invalid 422 Метка длиннее 64 символов или содержит управляющие символы. Сократите label либо не передавайте его.
image_search_disabled 503 Поиск по изображению временно недоступен. Повторите запрос позднее.
image_search_auth_error 401 Внешний поиск отклонил техническую авторизацию. Повторите запрос позднее; при постоянной ошибке обратитесь в поддержку.
image_search_timeout 504 Поиск по изображению не уложился в срок. Повторите запрос позднее.
image_search_network_error, image_search_protocol_error, image_search_upstream_error 502 Внешний поиск вернул сетевую, протокольную или временную ошибку. Повторите запрос позднее.
429 / rate_limit_exceeded 429 Локальный отказ BHAPI: исчерпан дневной, общий, Free или месячный лимит. Запрос не передан в WB, не списан как успешный и отображается в журнале как «Лимит». Проверьте лимиты в кабинете; уменьшите частоту запросов или дождитесь сброса квоты.
upstream_http_error 429, 5xx Настоящий отказ внешнего WB-сервиса. Даже при HTTP 429 он остаётся ошибкой внешнего сервиса и отображается в журнале как «Ошибка». Повторите запрос позже; при постоянной проблеме проверьте доступность WB.
— 500 Внутренняя ошибка сервиса. Повторите запрос позже, при постоянной проблеме свяжитесь с поддержкой.

Лимиты и квоты

Парсер WB использует token limits и отдельную тарифную квоту аккаунта для WB.

Тип лимитаОписаниеСброс / поведение
Дневной лимит Максимальное количество запросов к парсеру WB в сутки. Сбрасывается ежедневно по UTC. После исчерпания возвращается ошибка 429.
Общий лимит Суммарное количество запросов за всё время жизни токена. Не сбрасывается. При достижении лимита необходимо создать новый токен или изменить тариф.
Платный тариф WB Успешные запросы всех WB-ключей аккаунта в текущем месяце. Сбрасывается в начале календарного месяца, пока действует оплаченный период WB.
Free WB Если Free активен для WB: лимит успешных вызовов указан в тарифах, период 30 суток с первого ключа WB. Не сбрасывается и не перезапускается новым ключом; затем нужна платная подписка WB.
Rate limit Защита от слишком частых запросов подряд (ограничение скорости). Рекомендуется делать паузу 1–2 секунды между запросами, особенно при массовом парсинге.
Фильтры и пресеты Метаданные пресетов — 0 запросов; успешные discovery и search — по 1 запросу. Двухшаговый discovery + search расходует 2 успешных запроса.
Поиск по изображению Успешный поиск по одной картинке — 1 запрос. Ошибка валидации или внешнего сервиса не считается успешным расходом.
Совет. Используйте поиск и массовый сбор ссылок батчами, а затем обрабатывайте их с задержками, чтобы не упираться в ограничения WB и квоты портала.

Примеры: Python

Получить один товар по URL

Python — requests
import requests

API_URL = "https://bhapi.ru/wb/api/v1/item/by-url"
TOKEN = "ВАШ_API_TOKEN"

params = {
    "url": "https://www.wildberries.ru/catalog/770596537/detail.aspx",
}

response = requests.get(API_URL, params=params, headers={"X-API-Token": TOKEN}, timeout=30)
payload = response.json()

if payload["status"] == "ok" and payload["data"]["code"] == 200:
    item = payload["data"]["data"]
    print("ID товара:", item["item_id"])
    print("Название:", item["title"])
    print("Категория:", item["category_name"])
    print("Картинок:", len(item["main_imgs"]))
else:
    print("Ошибка:", payload)

Поиск по каталогу и вывод топа

Python — поиск
import requests

SEARCH_URL = "https://bhapi.ru/wb/api/v1/search"
TOKEN = "ВАШ_API_TOKEN"

payload = {
    "query": "аэрогриль объем 8 литров",
    "page": 1,
    "max_links": 10,
    "sort": "rate",
}

response = requests.post(
    SEARCH_URL,
    json=payload,
    headers={"X-API-Token": TOKEN},
    timeout=210,
)
payload = response.json()

data = payload["data"]
print(f"Всего найдено товаров: {data['total']}")
print(f"Показано на странице: {data['count']}")

for product in data["products"]:
    print(
        f"{product['id']}: {product['price']} ₽, "
        f"рейтинг {product['rating']}, отзывов {product['feedbacks']}"
    )

Примеры: cURL

Получить товар по URL

cURL
curl -X GET \
  "https://bhapi.ru/wb/api/v1/item/by-url?url=https://www.wildberries.ru/catalog/770596537/detail.aspx" \
  -H "X-API-Token: ВАШ_API_TOKEN"

Поиск по каталогу

cURL
# Базовый поиск
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{"query":"кроссовки"}'

# Страница 2, ограничение по количеству ссылок
curl -X POST "https://bhapi.ru/wb/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: ВАШ_API_TOKEN" \
  -d '{"query":"зимние ботинки","page":2,"max_links":50}'

Примеры: JavaScript

Fetch API (браузер / Node.js 18+)

JavaScript
const TOKEN = "ВАШ_API_TOKEN";
const BASE_URL = "https://bhapi.ru";

async function getWbItem(productUrl) {
  const params = new URLSearchParams({ url: productUrl });

  const response = await fetch(`${BASE_URL}/wb/api/v1/item/by-url?${params}`, {
    method: "GET",
    headers: { "X-API-Token": TOKEN },
  });

  const payload = await response.json();

  if (payload.status === "ok" && payload.data.code === 200) {
    return payload.data.data;
  }

  console.error("Ошибка WB:", payload);
  return null;
}

getWbItem("https://www.wildberries.ru/catalog/770596537/detail.aspx")
  .then((item) => {
    if (!item) return;
    console.log("Название:", item.title);
    console.log("Категория:", item.category_name);
    console.log("Первая картинка:", item.main_imgs[0]);
  });

Примеры: PHP

Получить товар по URL (PHP + cURL)

PHP
<?php

$apiUrl = "https://bhapi.ru/wb/api/v1/item/by-url";
$token  = "ВАШ_API_TOKEN";

$productUrl = "https://www.wildberries.ru/catalog/770596537/detail.aspx";

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $apiUrl . "?" . http_build_query(["url" => $productUrl]),
    CURLOPT_HTTPHEADER     => ["X-API-Token: " . $token],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);

$response = curl_exec($ch);
curl_close($ch);

$payload = json_decode($response, true);

if ($payload["status"] === "ok" && $payload["data"]["code"] === 200) {
    $item = $payload["data"]["data"];
    echo "Товар: " . $item["title"] . PHP_EOL;
    echo "Категория: " . $item["category_name"] . PHP_EOL;
} else {
    var_dump($payload);
}

Пакетная обработка (пример скрипта)

Ниже пример простого Python‑скрипта, который сначала выполняет поиск по каталогу, а затем последовательно запрашивает детали по каждому найденному товару с паузой между запросами.

Python — поиск + детали
import time
import requests

BASE_URL = "https://bhapi.ru"
TOKEN = "ВАШ_API_TOKEN"

def search(query: str, page: int = 1, limit: int = 10):
    resp = requests.post(
        f"{BASE_URL}/wb/api/v1/search",
        json={"query": query, "page": page, "max_links": limit},
        headers={"X-API-Token": TOKEN},
        timeout=210,
    )
    return resp.json()["data"]

def get_item(url: str):
    resp = requests.get(
        f"{BASE_URL}/wb/api/v1/item/by-url",
        params={"url": url},
        headers={"X-API-Token": TOKEN},
        timeout=30,
    )
    payload = resp.json()
    if payload["status"] == "ok" and payload["data"]["code"] == 200:
        return payload["data"]["data"]
    return None

data = search("аэрогриль объем 8 литров", page=1, limit=5)

items = []
for link in data["links"]:
    print("Парсим:", link)
    item = get_item(link)
    if item:
        items.append(item)
        print("  ✓", item["title"][:60])
    else:
        print("  ✗ не удалось получить данные")
    time.sleep(1.5)  # пауза, чтобы не превышать rate limit

print(f"Всего подробно получено товаров: {len(items)}")

Нужен готовый процесс, а не только API?

Соберём вокруг данных WB мониторинг, Telegram-бота, отчёт или рабочий кабинет. Начать можно с короткого описания ручной задачи — готовое ТЗ не требуется.

Обсудить автоматизацию WB