Документация парсера WB (Wildberries)
Парсер WB (Wildberries, Вайлдберриз) через API BHAPI возвращает карточки товаров, цены, изображения, характеристики и результаты поиска в JSON. Здесь описаны методы получения карточки, поиска товаров, каталога продавца и обзора отзывов, параметры запросов, формат ответов и примеры кода.
WB: получить товар по URL
/wb/api/v1/item/by-url
Парсит один товар Wildberries по URL и возвращает JSON с описанием, размерами, остатками, ценами, доставкой и таблицей замеров, если она предоставлена.
Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
url |
string | да | URL детальной карточки WB: https://www.wildberries.ru/catalog/<nm_id>/detail.aspx. |
pickup_point_id | integer | нет | Код ПВЗ из справочника, больше 0 и меньше 2**63. |
Заголовки
| Заголовок | Обязательный | Описание |
|---|---|---|
X-API-Token |
да | Ваш API‑токен портала. Передавайте только в заголовке. |
Пример запроса
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"}.
{
"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: поиск по каталогу
/wb/api/v1/search
Поиск по каталогу Wildberries с возможностью фильтрации и получения кратких данных по товарам.
Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
query |
string | да | Поисковый запрос в JSON-теле (строка, допускает кириллицу). |
page |
integer | нет | Номер страницы, по умолчанию 1. |
max_links |
integer | нет | Ограничение количества ссылок на страницу (опционально). |
sort |
string | нет |
Порядок выдачи: popular (по популярности, значение по умолчанию),
rate (по рейтингу), priceup (сначала дешевле),
pricedown (сначала дороже), newly (по обновлению)
или benefit (по выгоде).
|
min_price, max_price |
integer | нет | Фильтрация по цене в рублях. |
sale_type |
boolean | нет | true — только товары из распродажи. |
brand_ids |
integer[] | нет | Список ID брендов. |
preset |
string | нет | Готовая схема полей: footwear, clothing или headwear. |
preset_filters |
object | нет | Понятные значения полей выбранного пресета. Требует preset. |
characteristic_filters |
object | нет | Актуальные ключи характеристик и массивы целочисленных ID из discovery-ответа. |
pickup_point_id | integer | нет | Код ПВЗ из справочника. GET-алиас принимает его в query. |
Пример запроса
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,"max_links":10,"sort":"rate"}'
Структура ответа
| Поле | Описание |
|---|---|
query | Исходный поисковый запрос. |
page | Номер страницы. |
data.sort | Применённый порядок выдачи WB. |
total | Общее число товаров по запросу. |
links | Массив URL детальных карточек товаров. |
count | Количество ссылок в links. |
products | Список объектов с краткой информацией по каждому товару. |
Пример ответа
{
"status": "ok",
"data": {
"query": "аэрогриль объём 8 литров",
"page": 1,
"sort": "rate",
"total": 11628,
"links": [
"https://www.wildberries.ru/catalog/537724276/detail.aspx",
"https://www.wildberries.ru/catalog/523148127/detail.aspx",
"... другие ссылки ..."
],
"count": 10,
"products": [
{
"id": 537724276,
"link": "https://www.wildberries.ru/catalog/537724276/detail.aspx",
"price": 6381.0,
"rating": 4.9,
"feedbacks": 2780,
"description": "Аэрогриль электрический Air Fryer, Объём 8л,12 программ"
},
{
"id": 523148127,
"link": "https://www.wildberries.ru/catalog/523148127/detail.aspx",
"price": 7744.0,
"rating": 4.9,
"feedbacks": 394,
"description": "Аэрогриль электрический для дома 8 литров с Wi-fi и окошком"
}
// ... остальные товары ...
]
},
"saved_path": null
}
WB: поиск похожих товаров по изображению
/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_id | integer | нет | Поле multipart-формы: код ПВЗ из справочника. |
Content-Type: multipart/form-data
вручную: HTTP-клиент сам сформирует multipart boundary для поля файла.
Пример запроса
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
{
"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: метаданные пресетов категорий
/wb/api/v1/search/presets
Возвращает стабильные имена полей для трёх готовых пресетов: обувь
(footwear), одежда (clothing) и головные уборы
(headwear). Список не означает, что пресет подготовлен для каждой категории WB.
Пример запроса
curl -X GET "https://bhapi.ru/wb/api/v1/search/presets" \
-H "X-API-Token: ВАШ_API_TOKEN"
Структура ответа
| Поле | Тип | Описание |
|---|---|---|
data.presets[].name | string | Имя для поля preset. |
data.presets[].label | string | Русское название категории. |
data.presets[].fields[].name | string | Имя поля для preset_filters. |
data.presets[].fields[].label | string | Понятное название поля. |
data.presets[].fields[].multiple | boolean | Можно ли передать несколько значений. |
WB: динамические фильтры запроса
/wb/api/v1/search/filters
Возвращает актуальные группы характеристик и допустимые значения для конкретного поискового запроса. Фильтры зависят от запроса, региона и времени; полученный ID не следует считать постоянным глобальным словарём.
Тело запроса
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
query | string | да | Товар или категория для исследования. |
characteristic_filters | object | нет | Уже выбранные ID для контекстного уточнения списка. |
pickup_point_id | integer | нет | Код ПВЗ. Передайте тот же ПВЗ в последующем поиске, чтобы фильтры соответствовали региону. |
Пример 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
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.query | string | Исходный поисковый запрос. |
data.total | integer | Число товаров в текущем контексте. |
data.filters[].key | string | Ключ группы WB; поле итогового поиска выбирается по таблице ниже. |
data.filters[].values[].id | integer | Signed ID; отрицательный знак копируется без изменения. |
data.filters[].values[].name | string | Отображаемое значение. |
data.filters[].values[].count | integer | null | Доступное число товаров, если оно известно. |
Как перенести группу в поиск
Не переносите все группы механически в
characteristic_filters. Используйте назначение по ключу или типу группы.
| Группа discovery | Поле поиска | Правило |
|---|---|---|
Только ключи вида f<цифры> | characteristic_filters | Сохраните ключ и signed ID без изменения. |
fbrand | brand_ids | Передайте выбранные ID брендов массивом. |
Цена / базовая цена (priceU) | min_price, max_price | Передайте границы в рублях, а не ID значений группы. |
faction / распродажа | sale_type: true | Поддерживается только значение «Распродажа» с ID 1024637. |
faction или иная служебная группа
не поддерживается публичным поиском. Не переписывайте такой ключ в
characteristic_filters: используйте документированное поле, пресет или
пропустите группу.
Сценарии дополнительных фильтров
Значения внутри одного массива объединяются как OR внутри одной группы,
а разные ключи — как AND между группами. Пресеты и raw-ID можно
сочетать с ценой, распродажей и brand_ids в одном POST-поиске.
Обувь: коричневые мужские лоферы, размер 45
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 -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
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 -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: каталог продавца по ссылке
/wb/api/v1/seller/catalog
Возвращает каталог товаров конкретного продавца Wildberries по ссылке на магазин /seller/<id>.
Тело запроса
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
url |
string | да | URL продавца WB: https://www.wildberries.ru/seller/<supplier_id>. |
page |
integer | нет | Номер страницы каталога продавца, по умолчанию 1. |
pickup_point_id | integer | нет | Код ПВЗ из справочника. |
Заголовки
| Заголовок | Обязательный | Описание |
|---|---|---|
X-API-Token |
да | Ваш API‑токен портала. Передавайте только в заголовке. |
Пример запроса
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
{
"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
/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 -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
{
"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: пункты выдачи и доставка
/wb/api/v1/pickup-points
Возвращает справочник пунктов выдачи Wildberries. Используйте его, чтобы выбрать ПВЗ для получения цен, доступности товаров и данных доставки.
Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
query | string | нет | Поиск по части адреса без учёта регистра или точному коду ПВЗ. До 256 символов. Без параметра возвращается страница всего справочника. |
limit | integer | нет | Размер страницы: от 1 до 200, по умолчанию 50. |
offset | integer | нет | Смещение: от 0 до 250000, по умолчанию 0. Для следующей страницы увеличивайте на limit. |
Заголовки
| Заголовок | Обязательный | Описание |
|---|---|---|
X-API-Token | да | Ваш API-токен портала. Передавайте только в заголовке. |
Пример запроса
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 для выбора ПВЗ.
{
"status": "ok",
"data": {
"total": 1,
"count": 1,
"items": [
{
"id": 123,
"dest": -1234,
"address": "Москва, пример адреса"
}
]
}
}
Ключевые поля ответа
| Поле | Тип | Описание |
|---|---|---|
data.total | integer | Число совпадений до пагинации. |
data.count | integer | Количество ПВЗ на текущей странице. |
data.items | array | Пункты выдачи: id — код ПВЗ, address — адрес, dest — региональный код доставки, который сервис определяет сам. |
data.items[].country | string | Страна, если она присутствует в справочнике. |
data.items[].coordinates | array | Координаты [широта, долгота], если они доступны. |
ПВЗ по идентификатору
/wb/api/v1/pickup-points/{pickup_point_id}
Возвращает один пункт выдачи непосредственно в data. Требуется тот же заголовок X-API-Token.
| Параметр пути | Тип | Обязательный | Описание |
|---|---|---|---|
pickup_point_id | integer | да | Код из data.items[].id, больше 0 и меньше 2**63. |
Пример запроса
curl "https://bhapi.ru/wb/api/v1/pickup-points/123" \
-H "X-API-Token: ВАШ_API_TOKEN"
Успешный ответ 200 OK
{
"status": "ok",
"data": {
"id": 123,
"dest": -1234,
"address": "Москва, пример адреса"
}
}
Выбор ПВЗ для запросов товаров
Передайте код из справочника как необязательный pickup_point_id — положительное целое число меньше 2**63. Все пути в таблице имеют префикс /wb/api/v1.
| Метод | Где передавать |
|---|---|
GET item/by-url, search | Query-параметр. |
POST parse/single, search, search/filters, seller/catalog | Поле JSON. |
POST search/image | Поле multipart-формы. |
В JSON строки, дроби и логические значения отклоняются. Без параметра сохраняется прежнее поведение. Для отзывов и статических пресетов параметр не используется.
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/single | data.data.delivery_context | data.data.delivery_info |
search, search/image | data.delivery_context | data.products[].delivery_info |
seller/catalog | data.data.delivery_context | data.data.products[].delivery_info |
search/filters | data.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.
Ошибки
| Код API | HTTP-статус | Что делать |
|---|---|---|
pickup_point_not_found | 404 | Выберите другой ПВЗ из справочника. |
pickup_point_catalog_unavailable | 503 | Повторите запрос позже: справочник временно недоступен. |
Для 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 для одиночного товара структура такая:
| Поле | Тип | Описание |
|---|---|---|
code | integer | Код обработки запроса: 200 — успешный результат; остальные значения обозначают ошибку. |
msg | string | Текстовое описание результата ("success" или сообщение об ошибке). |
data | object | Карточка товара WB (см. раздел «Карточка товара» ниже). |
Карточка товара WB
Полная карточка находится в data.data ответа на GET /wb/api/v1/item/by-url и POST /wb/api/v1/parse/single. Массивы размеров и замеры не добавляются в краткие результаты поиска, поиска по изображению и каталога продавца. Схемы клиентов должны допускать новые поля ответа.
| Поле | Тип | Описание |
|---|---|---|
item_id | integer | Идентификатор товара WB (nm_id). |
product_url | string | URL детальной карточки товара. |
title | string | Название товара. |
currency | string | Код валюты, как правило RUB. |
price_info | object | Сводные цены одного варианта в рублях; правила выбора и значения полей описаны ниже. |
main_imgs | string[] | Массив URL основных изображений товара. |
additional_imgs | string[] | Дополнительные изображения (если есть). |
complectation | string | Комплектация из карточки товара. |
category_name | string | Название категории. |
category_path | string | Путь до категории (цепочка разделов). |
product_props | object | Словарь характеристик «название → значение» (объём памяти, цвет, ОС и т.п.). |
shop_info | object | Информация о продавце (см. ниже). |
review_info | object | Информация по отзывам (может быть пустым объектом). |
desc | string | Текстовое описание товара. |
source | string | Источник данных, обычно "wildberries". |
availability | integer | string | Сумма известных остатков всех размеров; 0 — известный ноль, "unknown" — итог неизвестен. Тип со строкой сохранён для совместимости. |
availability_status | string | in_stock, out_of_stock или unknown. Проверяйте это поле явно, без преобразования строки в boolean. |
price_size_option_id | integer | null | ID варианта, из которого выбрана сводная цена. |
delivery_info | object | Сводная доставка: сроки товара и стоимость варианта сводной цены. |
delivery_context | object | Контекст явно выбранного ПВЗ: ID, адрес и регион; см. «ПВЗ и доставка». |
sizes | object[] | Варианты одного артикула с собственной ценой, наличием, доставкой и складами. |
sizes_table | object | null | Таблица замеров продавца; null, если не предоставлена или не распознана. |
data_quality | object | Признак частичных данных и пути недостающих полей. |
data_freshness | object | Время сборки, возраст кэша и применённый регион. |
Размеры и складские остатки
sizes содержит варианты одного item_id, а не другие цвета с отдельными артикулами.
Порядок массива следует ответу WB и может меняться. Для связи используйте ID варианта.
| Поле sizes[] | Тип | Описание |
|---|---|---|
option_id | integer | null | ID варианта WB; связывает размер с замерами. Это не штрихкод и не артикул продавца. |
name, orig_name | string | null | Название размера WB и исходное название производителя. Могут различаться; форматы 50/194, 50-194, 48_182 сохраняются. |
availability | integer | null | Сумма известных остатков размера: 0 — нет в наличии, null — неизвестно. |
availability_status | string | in_stock, out_of_stock, unknown. |
price_info | object | Цена этого размера в рублях. |
delivery_info | object | Доставка этого размера без заимствования сроков из сводки товара. |
stocks | object[] | Складские записи: warehouse_id (integer | null), quantity (integer | null), собственный delivery_info. ID склада не раскрывает его название или адрес. |
Известный пустой список складов означает нулевой остаток в данном ответе и регионе. Отсутствующие или некорректные исходные остатки означают неизвестность. Если неизвестно хотя бы одно слагаемое, итог размера неизвестен; неизвестный размер делает неизвестным общий итог товара. Остаток не является резервом и не гарантирует доступное для заказа количество.
Цены и выбор сводного варианта
| Поле price_info | Тип | Описание |
|---|---|---|
pre_sale_price | number | null | Цена товара в рублях, полученная делением исходного значения WB на 100. В проверенных карточках — без дополнительной скидки Кошелька. |
origin_price | number | null | Базовая цена в рублях, обычно зачёркнутая на сайте. |
sale_price | number | null | Поле совместимости; сейчас null, цена с условной скидкой не вычисляется. |
debug.saleConditions | integer, необязательно | Исходное число 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_props | string[] | Названия колонок в исходном порядке WB; состав зависит от продавца. |
values | object[] | Строки замеров со следующими полями. |
tech_size | string | null | Исходный размер производителя, отдельно от значений колонок. |
chrt_id | integer | ID для связи с sizes[].option_id. |
details | string[] | Значения строки в порядке details_props. |
Связывайте строки по sizes[].option_id == sizes_table.values[].chrt_id, а не по позиции или названию.
tech_size не добавляется в начало details. Метка RU обозначает
колонку российского размера. Колонки не ограничены ростом, талией и бёдрами.
Таблица может содержать меньше строк, чем вариантов; отсутствие строки не означает отсутствия товара.
Качество и свежесть данных
| Объект | Поле | Тип и значение |
|---|---|---|
data_quality | is_partial | boolean — обнаружены недоступные или некорректные проверяемые данные. |
data_quality | missing_fields | string[] — пути, например sizes[1].stocks, sizes[1].price_info.pre_sale_price, sizes.truncated. |
data_freshness | assembled_at | string — UTC ISO 8601, время первоначальной сборки карточки; сохраняется при ответе из кэша. |
data_freshness | cache_hit | boolean — ответ получен из кэша парсера. |
data_freshness | cache_age_seconds | number — возраст записи кэша, 0 для нового ответа. |
data_freshness | cache_ttl_seconds | integer — настроенный срок хранения записи кэша. |
data_freshness | dest | integer — применённый регион, в том числе без явного ПВЗ. |
После проверки 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_name | string | Отображаемое название магазина (может быть пустой строкой). |
shop_id | string | Идентификатор магазина WB. |
seller_id | string | Идентификатор продавца (может совпадать с shop_id). |
Структура результата поиска
Объект data в ответе на /wb/api/v1/search детализированно описан ниже.
| Поле | Тип | Описание |
|---|---|---|
query | string | Исходный поисковый запрос. |
page | integer | Номер текущей страницы. |
total | integer | Общее число найденных товаров по всем страницам. |
links | string[] | Массив URL карточек товаров на текущей странице. |
count | integer | Количество элементов в массиве links. |
products | object[] | Массив кратких описаний товаров. |
Элемент products[i]
| Поле | Тип | Описание |
|---|---|---|
id | integer | nm_id товара WB. |
link | string | URL детальной карточки товара. |
price | float | null | Текущая цена в рублях (может быть null). |
rating | float | null | Рейтинг по отзывам. |
feedbacks | integer | null | Количество отзывов/оценок. |
description | string | null | Краткое текстовое описание товара. |
Коды ошибок
Таблицы и примеры этого раздела описывают ошибки legacy (формат по умолчанию).
Чтобы получать единый контракт ошибок, передайте заголовок
X-BHAPI-Error-Format: problem-v1.
Статусы некоторых ошибок в этом режиме отличаются; успешные ответы не меняются.
Общий справочник кодов, форматов и действий клиента →
Типичные коды ошибок при работе с парсером WB через портал BHAPI:
| Код API | HTTP-статус | Описание | Что делать |
|---|---|---|---|
pickup_point_not_found | 404 | ПВЗ не найден или не имеет доступного региона доставки. | Выберите другой id из справочника. |
pickup_point_catalog_unavailable | 503 | Справочник ПВЗ временно недоступен. | Повторите запрос позже. |
| — | 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 запрос. | Ошибка валидации или внешнего сервиса не считается успешным расходом. |
Примеры: Python
Получить один товар по URL
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)
Поиск по каталогу и вывод топа
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 -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 -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+)
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
$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‑скрипта, который сначала выполняет поиск по каталогу, а затем последовательно запрашивает детали по каждому найденному товару с паузой между запросами.
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