Files
supermarket/cursor_forbidden_api.md

424 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ошибка Forbidden в API Магнит
_Exported on 12/14/2025 at 03:06:00 GMT+5 from Cursor (2.2.20)_
---
**User**
@.cursor/plans/supermarket_scraper_system_1af4ed29.plan.md
Вопрос сейчас только про api магнит
https://magnit.ru/webgate/v2/goods/1000257489/stores/992301?storetype=6&catalogtype=1
ответ Forbidden
Transaction ID: 2b7f613f-b7fe-4f95-9dd4-b30c1f5cb4a5
Хотя в браузере работает у них на сайте
https://magnit.ru/product/1000257489-chay_chernyy_greenfield_english_edition_100pak?shopCode=992301&shopType=6
вот заголовки в браузере
URL запроса:
https://magnit.ru/webgate/v2/goods/1000257489/stores/992301?storetype=6&catalogtype=1
Метод запроса:
GET
Код статуса:
200 OK
Удаленный адрес:
178.248.238.72:443
Правило для URL перехода:
origin
content-encoding:
gzip
content-type:
application/json
date:
Sat, 13 Dec 2025 21:41:24 GMT
document-policy:
js-profiling
referrer-policy:
origin
server:
QRATOR
strict-transport-security:
max-age=31536000; includeSubDomains
vary:
Accept-Encoding,Accept-Encoding
x-content-type-options:
nosniff
x-frame-options:
SAMEORIGIN
x-trace-id:
544850473b9c35d2d1c00538cc1d16c6
x-xss-protection:
1
:authority:
magnit.ru
:method:
GET
:path:
/webgate/v2/goods/1000257489/stores/992301?storetype=6&catalogtype=1
:scheme:
https
accept:
*/*
accept-encoding:
gzip, deflate, br, zstd
accept-language:
ru,en-US;q=0.9,en;q=0.8
baggage:
sentry-environment=production,sentry-public_key=7992e659d14bf5d8da08d2e6a0706d0a,sentry-trace_id=596895b1cc7b4c05935d288b1cc91e8a,sentry-sampled=false,sentry-sample_rand=0.6716192411675364,sentry-sample_rate=0.05
content-type:
application/json
cookie:
nmg_dt=; shopCode=992301; x_shop_type=ME; mg_udi=9D4909B8-9F79-5B1D-8457-EA519EC9AA3F; oxxfgh=ef3934b0-03b7-44fc-b6d8-9b0dd7412ea3%230%237884000000%235000%231800000%2312840; uwyii=b172df84-99bb-4b86-51b5-909db1474363; nmg_sp=Y; mg_uac=1; mg_adlt=Y; uwyiert=65182acc-a917-c963-d7fe-a14c0cab4e8d
dnt:
1
priority:
u=1, i
referer:
https://magnit.ru/
sec-ch-ua:
"Not?A_Brand";v="99", "Chromium";v="130"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"Windows"
sec-fetch-dest:
empty
sec-fetch-mode:
cors
sec-fetch-site:
same-origin
sec-gpc:
1
sentry-trace:
596895b1cc7b4c05935d288b1cc91e8a-b581de5bc3a814d5-0
user-agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
x-app-version:
2025.12.12-16.56
x-client-name:
magnit
x-device-id:
9D4909B8-9F79-5B1D-8457-EA519EC9AA3F
x-device-platform:
Web
x-device-tag:
disabled
x-new-magnit:
true
x-platform-version:
Windows Chrome 130
---
**Cursor**
API Магнита возвращает 403, потому что требуется авторизация и корректные заголовки. Анализирую требования и способы их соблюдения:
API Магнита возвращает 403, потому что требуется авторизация и корректные заголовки. По заголовкам из браузера видно, что нужны:
## Проблема
API проверяет:
1. Cookies (сессия)
2. Заголовки, имитирующие браузер
3. Referer и origin
## Решение
### Вариант 1: Использовать Playwright для получения cookies и заголовков
Сначала зайти на сайт через Playwright, получить cookies, затем использовать их в HTTP-запросах:
```typescript
// src/scrapers/api/magnit/MagnitApiScraper.ts
import { chromium, Browser, Page } from 'playwright';
import axios, { AxiosInstance } from 'axios';
export class MagnitApiScraper {
private browser: Browser | null = null;
private page: Page | null = null;
private httpClient: AxiosInstance;
private cookies: string = '';
private deviceId: string = '';
constructor() {
this.httpClient = axios.create({
baseURL: 'https://magnit.ru',
headers: {
'accept': '*/*',
'accept-language': 'ru,en-US;q=0.9,en;q=0.8',
'content-type': 'application/json',
'referer': 'https://magnit.ru/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
'x-app-version': '2025.12.12-16.56',
'x-client-name': 'magnit',
'x-device-platform': 'Web',
'x-device-tag': 'disabled',
'x-new-magnit': 'true',
'x-platform-version': 'Windows Chrome 130',
}
});
}
async initialize() {
// Запускаем браузер и получаем cookies
this.browser = await chromium.launch({ headless: true });
this.page = await this.browser.newPage();
// Переходим на главную страницу
await this.page.goto('https://magnit.ru/', { waitUntil: 'networkidle' });
// Получаем cookies
const cookies = await this.page.context().cookies();
this.cookies = cookies.map(c => `${c.name}=${c.value}`).join('; ');
// Извлекаем device-id из cookies
const mgUdiCookie = cookies.find(c => c.name === 'mg_udi');
if (mgUdiCookie) {
this.deviceId = mgUdiCookie.value;
} else {
// Генерируем новый device-id если нет
this.deviceId = this.generateDeviceId();
}
// Обновляем заголовки с device-id
this.httpClient.defaults.headers['x-device-id'] = this.deviceId;
this.httpClient.defaults.headers['cookie'] = this.cookies;
}
async getProductStores(productId: string, storeCode: string = '992301') {
if (!this.page) {
await this.initialize();
}
try {
const response = await this.httpClient.get(
`/webgate/v2/goods/${productId}/stores/${storeCode}`,
{
params: {
storetype: '6',
catalogtype: '1'
}
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error) && error.response?.status === 403) {
// Если 403, обновляем сессию
await this.initialize();
return this.getProductStores(productId, storeCode);
}
throw error;
}
}
private generateDeviceId(): string {
// Генерация UUID формата: 9D4909B8-9F79-5B1D-8457-EA519EC9AA3F
return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, () => {
return (Math.random() * 16 | 0).toString(16).toUpperCase();
});
}
async close() {
if (this.browser) {
await this.browser.close();
}
}
}
```
### Вариант 2: Использовать Playwright напрямую для API-запросов
Делать запросы через контекст браузера Playwright:
```typescript
async getProductStoresViaBrowser(productId: string, storeCode: string = '992301') {
if (!this.page) {
await this.initialize();
}
// Используем request API Playwright, который автоматически использует cookies браузера
const response = await this.page!.request.get(
`https://magnit.ru/webgate/v2/goods/${productId}/stores/${storeCode}?storetype=6&catalogtype=1`,
{
headers: {
'accept': '*/*',
'referer': 'https://magnit.ru/',
'x-app-version': '2025.12.12-16.56',
'x-client-name': 'magnit',
'x-device-platform': 'Web',
'x-new-magnit': 'true',
}
}
);
if (!response.ok()) {
throw new Error(`API request failed: ${response.status()}`);
}
return await response.json();
}
```
## Важные моменты
1. Обязательные заголовки:
- `x-device-id` — из cookie `mg_udi`
- `x-client-name: magnit`
- `x-device-platform: Web`
- `referer: https://magnit.ru/`
- `cookie` — все cookies из сессии
2. Cookies, которые нужно передавать:
- `shopCode=992301`
- `mg_udi` (device-id)
- `oxxfgh`, `uwyii`, `uwyiert` (сессионные)
3. Рекомендация: использовать Playwright для инициализации сессии и получения cookies, затем делать запросы через `page.request` или передавать cookies в axios.
Нужна полная реализация `MagnitApiScraper` с этой логикой?
```typescript
// src/scrapers/api/magnit/MagnitApiScraper.ts
import { chromium, Browser, Page } from 'playwright';
import axios, { AxiosInstance } from 'axios';
export class MagnitApiScraper {
private browser: Browser | null = null;
private page: Page | null = null;
private httpClient: AxiosInstance;
private cookies: string = '';
private deviceId: string = '';
constructor() {
this.httpClient = axios.create({
baseURL: 'https://magnit.ru',
headers: {
'accept': '*/*',
'accept-language': 'ru,en-US;q=0.9,en;q=0.8',
'content-type': 'application/json',
'referer': 'https://magnit.ru/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
'x-app-version': '2025.12.12-16.56',
'x-client-name': 'magnit',
'x-device-platform': 'Web',
'x-device-tag': 'disabled',
'x-new-magnit': 'true',
'x-platform-version': 'Windows Chrome 130',
}
});
}
async initialize() {
// Запускаем браузер и получаем cookies
this.browser = await chromium.launch({ headless: true });
this.page = await this.browser.newPage();
// Переходим на главную страницу
await this.page.goto('https://magnit.ru/', { waitUntil: 'networkidle' });
// Получаем cookies
const cookies = await this.page.context().cookies();
this.cookies = cookies.map(c => `${c.name}=${c.value}`).join('; ');
// Извлекаем device-id из cookies
const mgUdiCookie = cookies.find(c => c.name === 'mg_udi');
if (mgUdiCookie) {
this.deviceId = mgUdiCookie.value;
} else {
// Генерируем новый device-id если нет
this.deviceId = this.generateDeviceId();
}
// Обновляем заголовки с device-id
this.httpClient.defaults.headers['x-device-id'] = this.deviceId;
this.httpClient.defaults.headers['cookie'] = this.cookies;
}
async getProductStores(productId: string, storeCode: string = '992301') {
if (!this.page) {
await this.initialize();
}
try {
const response = await this.httpClient.get(
`/webgate/v2/goods/${productId}/stores/${storeCode}`,
{
params: {
storetype: '6',
catalogtype: '1'
}
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error) && error.response?.status === 403) {
// Если 403, обновляем сессию
await this.initialize();
return this.getProductStores(productId, storeCode);
}
throw error;
}
}
private generateDeviceId(): string {
// Генерация UUID формата: 9D4909B8-9F79-5B1D-8457-EA519EC9AA3F
return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, () => {
return (Math.random() * 16 | 0).toString(16).toUpperCase();
});
}
async close() {
if (this.browser) {
await this.browser.close();
}
}
}
```
```typescript
async getProductStoresViaBrowser(productId: string, storeCode: string = '992301') {
if (!this.page) {
await this.initialize();
}
// Используем request API Playwright, который автоматически использует cookies браузера
const response = await this.page!.request.get(
`https://magnit.ru/webgate/v2/goods/${productId}/stores/${storeCode}?storetype=6&catalogtype=1`,
{
headers: {
'accept': '*/*',
'referer': 'https://magnit.ru/',
'x-app-version': '2025.12.12-16.56',
'x-client-name': 'magnit',
'x-device-platform': 'Web',
'x-new-magnit': 'true',
}
}
);
if (!response.ok()) {
throw new Error(`API request failed: ${response.status()}`);
}
return await response.json();
}
```
Проверяю структуру проекта и план, чтобы понять текущее состояние и что нужно реализовать:
Проверяю, есть ли уже код для работы с API Магнита. Если нет, предложу решение для обхода 403 Forbidden.