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

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

Парсит страницу одного товара на 1688.com и возвращает структурированные данные.

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

ПараметрТипОбязательныйОписание
url string да Полный URL страницы товара на 1688.com. Поддерживаются домены detail.1688.com, m.1688.com, offer.1688.com.

Заголовки

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

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

cURL
curl -X GET \
  "https://bhapi.ru/1688/api/v1/item/by-url?url=https://detail.1688.com/offer/745678901234.html" \
  -H "X-API-Token: ваш_токен_здесь"

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

JSON
{
  "code": 200,
  "message": "OK",
  "data": {
    "item_id": "745678901234",
    "url": "https://detail.1688.com/offer/745678901234.html",
    "title": "2024新款春夏男士休闲运动鞋 透气网面跑步鞋",
    "images": [
      "https://cbu01.alicdn.com/img/ibank/O1CN01abcdef.jpg",
      "https://cbu01.alicdn.com/img/ibank/O1CN01ghijkl.jpg",
      "https://cbu01.alicdn.com/img/ibank/O1CN01mnopqr.jpg"
    ],
    "desc_images": [
      "https://cbu01.alicdn.com/img/ibank/O1CN01desc01.jpg",
      "https://cbu01.alicdn.com/img/ibank/O1CN01desc02.jpg"
    ],
    "detail_description": "Высококачественная спортивная обувь...",
    "price_info": {
      "currency": "CNY",
      "price": 68.0,
      "original_price": 128.0,
      "tiers": [
        {"from_qty": 1, "to_qty": 2, "price": 78.0},
        {"from_qty": 3, "to_qty": 29, "price": 68.0},
        {"from_qty": 30, "to_qty": null, "price": 58.0}
      ]
    },
    "inventory": 15000,
    "rating": 4.8,
    "review_count": 342,
    "sold_count": 12500,
    "attributes": {
      "Материал подошвы": "EVA+резина",
      "Материал верха": "Сетка+искусственная кожа",
      "Стиль": "Спортивный",
      "Сезон": "Весна/Лето"
    },
    "video_url": "https://cloud.video.taobao.com/play/u/xxx/e/6/t/1/xxx.mp4",
    "video_poster": "https://cbu01.alicdn.com/img/poster.jpg",
    "video_urls": [
      "https://cloud.video.taobao.com/play/u/xxx/e/6/t/1/xxx.mp4"
    ],
    "pack_info": [
      {
        "variant": "Чёрный",
        "length_cm": 33.0,
        "width_cm": 21.0,
        "height_cm": 12.0,
        "volume_cm3": 8316.0,
        "weight_g": 680.0
      }
    ],
    "shop": {
      "shop_id": "b2b-2210xxxxxx",
      "shop_name": "莆田市鑫达鞋业有限公司",
      "shop_url": "https://shop1234.1688.com"
    },
    "skus": [
      {
        "sku_id": "5021639372635",
        "title": "Чёрный / 39",
        "attributes": {"颜色": "黑色", "尺码": "39"},
        "price": 68.0,
        "inventory": 500
      }
    ],
    "raw": null
  }
}
Совет. Поле raw содержит дополнительные данные, которые не удалось нормализовать. Оно может быть полезно для отладки или получения нестандартных данных.

1688: пакетный парсинг из файла

POST /1688/api/v1/item/by-file

Загрузите текстовый файл со списком URL (по одному в строке). Сервис последовательно обработает каждый URL и вернёт массив результатов.

Параметры

ПараметрТипОбязательныйОписание
file file (multipart) да Текстовый файл UTF-8 со списком URL. По одному URL на строку.

Ограничения

ПараметрЗначение
Максимальный размер файла1 МБ
Максимальное количество URL500
КодировкаUTF-8

Пример файла

urls.txt
https://detail.1688.com/offer/745678901234.html
https://detail.1688.com/offer/745678905678.html
https://detail.1688.com/offer/745678909012.html

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

cURL
curl -X POST "https://bhapi.ru/1688/api/v1/item/by-file" \
  -H "X-API-Token: ваш_токен_здесь" \
  -F "file=@urls.txt"

Формат ответа

Массив объектов ItemDetailResponse. Ошибки для отдельных URL не прерывают весь запрос:

JSON (массив)
[
  {
    "code": 200,
    "message": "OK",
    "data": { "item_id": "745678901234", "title": "...", ... }
  },
  {
    "code": 422,
    "message": "URL не является ссылкой на товар 1688.com.",
    "data": { "item_id": "unknown", "url": "https://example.com/wrong", ... }
  }
]

Формат ответа

Для парсера 1688 все ответы API имеют единую обёртку ItemDetailResponse. Поле code содержит бизнес-код результата, message — текстовое описание, data — данные товара.

ПолеТипОписание
codeintegerКод результата. 200 — успех, остальные — ошибки.
messagestringЧеловекочитаемое описание: "OK", сообщение об ошибке.
dataItemDetailОбъект с данными о товаре (см. Структура ItemDetail).

Структура ItemDetail

Основной объект с данными товара парсера 1688, возвращаемый в поле data.

ПолеТипОписание
item_idstringИдентификатор товара на 1688.
urlstringОригинальный URL товара.
titlestringНазвание товара (на языке оригинала).
imagesstring[]Массив URL основных изображений товара.
desc_imagesstring[]URL изображений из описания товара (блок «подробности»).
detail_descriptionstring | nullТекстовое описание товара (характеристики, производство и т.п.).
price_infoPriceInfo | nullЦеновая информация (см. Цены и SKU).
inventoryinteger | nullОбщий остаток товара на складе.
ratingfloat | nullРейтинг товара (например, 4.8 из 5).
review_countinteger | nullКоличество отзывов о товаре.
sold_countinteger | nullКоличество продаж за период.
attributesobjectХарактеристики: материал, стиль, сезон и т.д. Ключ — название, значение — текст.
video_urlstring | nullURL первого видео товара.
video_posterstring | nullПостер (превью) первого видео.
video_urlsstring[]Все URL видео товара.
pack_infoPackInfoItem[]Информация об упаковке по вариантам (размеры, вес).
shopShopInfo | nullИнформация о магазине (см. Информация о магазине).
skusSkuItem[]Список SKU / вариантов товара.
rawobject | nullДополнительные необработанные данные для отладки.

Цены и SKU

PriceInfo

ПолеТипОписание
currencystringКод валюты (CNY).
pricefloatБазовая цена товара.
original_pricefloat | nullСтарая цена (если есть скидка).
tiersPriceTier[]Оптовые ценовые ступени.

PriceTier — оптовые ступени

На 1688 цена зависит от количества. Чем больше заказ, тем ниже цена за единицу.

ПолеТипОписание
from_qtyinteger | nullМинимальное количество (включительно).
to_qtyinteger | nullМаксимальное количество (включительно). null — без верхней границы.
pricefloatЦена за единицу в этом диапазоне.
Пример оптовых ступеней
"tiers": [
  {"from_qty": 1,   "to_qty": 2,    "price": 78.0},    // 1-2 шт: 78 ¥
  {"from_qty": 3,   "to_qty": 29,   "price": 68.0},    // 3-29 шт: 68 ¥
  {"from_qty": 30,  "to_qty": null,  "price": 58.0}     // от 30 шт: 58 ¥
]

SkuItem — варианты товара

ПолеТипОписание
sku_idstringИдентификатор SKU.
titlestringНазвание варианта (например, «Чёрный / 42»).
attributesobjectАтрибуты: цвет, размер и т.д.
pricefloat | nullЦена конкретного SKU (если отличается).
inventoryinteger | nullОстаток по этому варианту.

PackInfoItem — упаковка

ПолеТипОписание
variantstringНазвание варианта (цвет).
length_cmfloat | nullДлина упаковки, см.
width_cmfloat | nullШирина, см.
height_cmfloat | nullВысота, см.
volume_cm3float | nullОбъём, см³.
weight_gfloat | nullВес, г.

Информация о магазине

ПолеТипОписание
shop_idstring | nullИдентификатор магазина на 1688.
shop_namestring | nullНазвание магазина/компании.
shop_urlstring | nullURL магазина.

Коды ошибок

При ошибке API возвращает JSON с кодом и описанием:

Формат ошибки
{
  "code": 422,
  "message": "URL не является ссылкой на товар 1688.com."
}
КодHTTP StatusОписаниеЧто делать
400 Bad Request Некорректный запрос. Проверьте формат запроса и параметры.
401 Unauthorized Токен не передан или невалиден. Убедитесь, что токен передан через X-API-Token или apiToken.
403 Forbidden Токен заблокирован или истёк. Создайте новый токен в личном кабинете.
413 Payload Too Large Размер файла превышает 1 МБ. Уменьшите файл или разбейте на несколько.
417 Expectation Failed Товар найден, но не удалось извлечь данные. Возможно, страница товара изменена, снята с продажи или защищена. Попробуйте позже.
422 Unprocessable Entity URL не является ссылкой на товар 1688. Проверьте, что URL ведёт на detail.1688.com, m.1688.com или offer.1688.com.
429 Too Many Requests Исчерпан дневной или общий лимит запросов. Подождите до следующего дня или увеличьте лимит в настройках тарифа.
439 Rate Limited Слишком частые запросы (rate limit). Добавьте задержку между запросами (1-2 секунды).
499 Client Closed Клиент закрыл соединение до завершения обработки. Увеличьте таймаут на стороне клиента (рекомендуется 30+ секунд).
500 Internal Server Error Внутренняя ошибка сервиса. Повторите запрос через несколько секунд. Если ошибка повторяется — свяжитесь с поддержкой.
503 Service Unavailable Сервис временно недоступен. Попробуйте позже. Проводятся технические работы.

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

У каждого API-токена есть два типа лимитов:

Тип лимитаОписаниеСброс
Дневной (limit_daily) Максимальное число запросов в сутки (UTC). Каждый день в 00:00 UTC.
Общий (limit_total) Максимальное общее число запросов за всё время жизни токена. Не сбрасывается. При исчерпании — создайте новый токен.
Совет. Следите за расходом в личном кабинете. Там отображается статистика использования каждого токена: количество запросов, успешность и последний запрос.

Рекомендации по оптимизации:

  • Добавляйте паузу 1-2 секунды между запросами, чтобы не попасть под rate limit.
  • Используйте пакетный эндпоинт /by-file вместо последовательных /by-url.
  • Кэшируйте результаты на своей стороне — данные товара обновляются не чаще раза в час.

Примеры: Python

Простой запрос одного товара

Python — requests
import requests

API_URL = "https://bhapi.ru/api/v1/item/by-url"
TOKEN = "ваш_токен_здесь"

response = requests.get(
    API_URL,
    params={"url": "https://detail.1688.com/offer/745678901234.html"},
    headers={"X-API-Token": TOKEN},
    timeout=30,
)

data = response.json()

if data["code"] == 200:
    item = data["data"]
    print(f"Товар: {item['title']}")
    print(f"Цена: {item['price_info']['price']} {item['price_info']['currency']}")
    print(f"Изображений: {len(item['images'])}")
    print(f"SKU вариантов: {len(item['skus'])}")
    print(f"Магазин: {item['shop']['shop_name']}")
else:
    print(f"Ошибка {data['code']}: {data['message']}")

Пакетная обработка списка URL

Python — пакетный запрос
import requests
import json
import time

API_URL = "https://bhapi.ru/api/v1/item/by-url"
TOKEN = "ваш_токен_здесь"

urls = [
    "https://detail.1688.com/offer/745678901234.html",
    "https://detail.1688.com/offer/745678905678.html",
    "https://detail.1688.com/offer/745678909012.html",
]

results = []

for url in urls:
    response = requests.get(
        API_URL,
        params={"url": url},
        headers={"X-API-Token": TOKEN},
        timeout=30,
    )
    data = response.json()
    results.append(data)

    if data["code"] == 200:
        print(f"✓ {data['data']['title'][:50]}…")
    else:
        print(f"✗ Ошибка {data['code']}: {data['message']}")

    time.sleep(1.5)  # пауза, чтобы не превысить rate limit

# Сохраняем результаты
with open("results.json", "w", encoding="utf-8") as f:
    json.dump(results, f, ensure_ascii=False, indent=2)

print(f"\nОбработано: {len(results)} товаров")

Загрузка файла с URL

Python — by-file
import requests

API_URL = "https://bhapi.ru/api/v1/item/by-file"
TOKEN = "ваш_токен_здесь"

with open("urls.txt", "rb") as f:
    response = requests.post(
        API_URL,
        headers={"X-API-Token": TOKEN},
        files={"file": ("urls.txt", f, "text/plain")},
        timeout=120,  # файл может обрабатываться долго
    )

results = response.json()

success = sum(1 for r in results if r["code"] == 200)
print(f"Успешно: {success}/{len(results)}")

for item in results:
    if item["code"] == 200:
        d = item["data"]
        print(f"  {d['item_id']}: {d['title'][:40]}… — {d['price_info']['price']} CNY")
    else:
        print(f"  Ошибка {item['code']}: {item['message']}")

Извлечение оптовых цен

Python — работа с ценовыми ступенями
# Предположим, item — это data["data"] из успешного ответа

price_info = item["price_info"]

print(f"Базовая цена: {price_info['price']} {price_info['currency']}")

if price_info.get("original_price"):
    discount = round((1 - price_info['price'] / price_info['original_price']) * 100)
    print(f"Скидка: {discount}% (было {price_info['original_price']})")

print("\nОптовые ступени:")
for tier in price_info["tiers"]:
    to = tier["to_qty"] or "∞"
    print(f"  {tier['from_qty']}–{to} шт: {tier['price']} ¥")

# Рассчитаем стоимость заказа из 50 единиц
order_qty = 50
applicable_price = price_info["price"]
for tier in price_info["tiers"]:
    if tier["from_qty"] <= order_qty:
        if tier["to_qty"] is None or tier["to_qty"] >= order_qty:
            applicable_price = tier["price"]

total = applicable_price * order_qty
print(f"\nЗаказ {order_qty} шт: {applicable_price} × {order_qty} = {total} ¥")

Примеры: cURL

Получить данные товара

cURL
# Через заголовок (рекомендуется)
curl -X GET \
  "https://bhapi.ru/api/v1/item/by-url?url=https://detail.1688.com/offer/745678901234.html" \
  -H "X-API-Token: ваш_токен"

# Через query-параметр
curl -X GET \
  "https://bhapi.ru/api/v1/item-by-url?url=https://detail.1688.com/offer/745678901234.html&apiToken=ваш_токен"

Загрузить файл с URL

cURL
curl -X POST "https://bhapi.ru/api/v1/item/by-file" \
  -H "X-API-Token: ваш_токен" \
  -F "file=@urls.txt"

Сохранить результат в файл

cURL — с записью в файл
curl -s -X GET \
  "https://bhapi.ru/api/v1/item/by-url?url=https://detail.1688.com/offer/745678901234.html" \
  -H "X-API-Token: ваш_токен" | python3 -m json.tool > result.json

Примеры: JavaScript

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

JavaScript
const API_URL = "https://bhapi.ru/api/v1/item/by-url";
const TOKEN = "ваш_токен_здесь";

async function getItem(productUrl) {
  const params = new URLSearchParams({ url: productUrl });
  const response = await fetch(`${API_URL}?${params}`, {
    method: "GET",
    headers: { "X-API-Token": TOKEN },
  });

  const data = await response.json();

  if (data.code === 200) {
    console.log("Товар:", data.data.title);
    console.log("Цена:", data.data.price_info.price, data.data.price_info.currency);
    console.log("SKU:", data.data.skus.length, "вариантов");
    return data.data;
  } else {
    console.error(`Ошибка ${data.code}: ${data.message}`);
    return null;
  }
}

getItem("https://detail.1688.com/offer/745678901234.html");

Node.js с axios

JavaScript — axios
const axios = require("axios");

const api = axios.create({
  baseURL: "https://bhapi.ru",
  headers: { "X-API-Token": "ваш_токен" },
  timeout: 30000,
});

async function parseProduct(url) {
  try {
    const { data } = await api.get("/api/v1/item/by-url", {
      params: { url },
    });

    if (data.code === 200) {
      return data.data;
    }
    throw new Error(`API ошибка ${data.code}: ${data.message}`);
  } catch (err) {
    console.error("Ошибка:", err.message);
    return null;
  }
}

parseProduct("https://detail.1688.com/offer/745678901234.html")
  .then(item => {
    if (item) {
      console.log(JSON.stringify(item, null, 2));
    }
  });

Примеры: PHP

PHP с cURL

PHP
<?php

$apiUrl = "https://bhapi.ru/api/v1/item/by-url";
$token  = "ваш_токен_здесь";

$productUrl = "https://detail.1688.com/offer/745678901234.html";

$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);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

if ($data["code"] === 200) {
    $item = $data["data"];
    echo "Товар: " . $item["title"] . "\n";
    echo "Цена: " . $item["price_info"]["price"] . " " . $item["price_info"]["currency"] . "\n";
    echo "Вариантов: " . count($item["skus"]) . "\n";
} else {
    echo "Ошибка {$data['code']}: {$data['message']}\n";
}

Загрузка файла (PHP)

PHP — пакетный парсинг
<?php

$apiUrl = "https://bhapi.ru/api/v1/item/by-file";
$token  = "ваш_токен_здесь";

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $apiUrl,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ["X-API-Token: " . $token],
    CURLOPT_POSTFIELDS     => ["file" => new CURLFile("urls.txt", "text/plain")],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 120,
]);

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

$results = json_decode($response, true);

foreach ($results as $item) {
    if ($item["code"] === 200) {
        echo "✓ " . $item["data"]["title"] . "\n";
    } else {
        echo "✗ Ошибка {$item['code']}: {$item['message']}\n";
    }
}

Пакетная обработка

Для парсинга большого количества товаров рекомендуем использовать эндпоинт /by-file или скрипт с паузами между запросами. Ниже — пример скрипта с обработкой ошибок и повторными попытками.

Python — с повторными попытками
import requests
import time
import json

API_URL = "https://bhapi.ru/api/v1/item/by-url"
TOKEN = "ваш_токен_здесь"
MAX_RETRIES = 3
DELAY = 2  # секунды между запросами

def fetch_item(url: str) -> dict | None:
    """Получает данные товара с повторными попытками."""
    for attempt in range(1, MAX_RETRIES + 1):
        try:
            resp = requests.get(
                API_URL,
                params={"url": url},
                headers={"X-API-Token": TOKEN},
                timeout=30,
            )
            data = resp.json()

            if data["code"] == 200:
                return data["data"]

            # Ошибки, при которых повтор не поможет
            if data["code"] in (401, 403, 422):
                print(f"  Фатальная ошибка {data['code']}: {data['message']}")
                return None

            # Ошибки rate limit — ждём дольше
            if data["code"] in (429, 439):
                wait = DELAY * attempt * 5
                print(f"  Rate limit, ожидание {wait}с...")
                time.sleep(wait)
                continue

            # Серверные ошибки — повторяем
            print(f"  Попытка {attempt}/{MAX_RETRIES}: ошибка {data['code']}")

        except requests.RequestException as e:
            print(f"  Попытка {attempt}/{MAX_RETRIES}: {e}")

        time.sleep(DELAY * attempt)

    return None


# Основной цикл
urls = open("urls.txt").read().strip().splitlines()
results = []

for i, url in enumerate(urls, 1):
    print(f"[{i}/{len(urls)}] {url[:60]}...")
    item = fetch_item(url)

    if item:
        results.append(item)
        print(f"  ✓ {item['title'][:50]}")
    else:
        print(f"  ✗ Не удалось получить данные")

    time.sleep(DELAY)

with open("results.json", "w", encoding="utf-8") as f:
    json.dump(results, f, ensure_ascii=False, indent=2)

print(f"\nГотово: {len(results)}/{len(urls)} товаров")

Формат ответа

Для парсера 1688 все ответы API имеют единую обёртку ItemDetailResponse. Поле code содержит бизнес-код результата, message — текстовое описание, data — данные товара.

ПолеТипОписание
codeintegerКод результата. 200 — успех, остальные — ошибки.
messagestringЧеловекочитаемое описание: "OK", сообщение об ошибке.
dataItemDetailОбъект с данными о товаре (см. Структура ItemDetail).