Когда UI показывает неправильные данные, вкладка Network в DevTools говорит тебе: API вернул неправильные данные (баг бэкенда) или правильные данные отобразились некорректно (баг фронтенда). Для этой диагностики нужно понимать как устроены REST-запросы и ответы. Статья разбирает HTTP-методы, статус-коды (включая почему успешный POST должен возвращать 201, а не 200), заголовки аутентификации и как делать прямые API-вызовы в Playwright-тестах.

Базовая концепция: запрос и ответ

API (Application Programming Interface): способ для двух программ общаться между собой. REST API: конкретный стиль API который использует HTTP, тот же протокол которым браузер загружает сайты.

Разговор всегда строится одинаково: твой код (или тест) отправляет запрос, а сервер обрабатывает его и отправляет обратно ответ.

Всё. Остальное: детали того как эти две вещи устроены.

Анатомия HTTP-запроса

Каждый запрос состоит из четырёх частей.

1. Метод (глагол)

Метод говорит серверу что ты хочешь сделать:

| Метод | Что делает | Как сказать |

|--------|-------------|-------------|

| GET | Получить данные | «Дай мне это» |

| POST | Создать что-то новое | «Вот новые данные, сохрани» |

| PUT | Заменить целиком | «Замени это на мою новую версию» |

| PATCH | Обновить часть | «Измени только это поле» |

| DELETE | Удалить | «Удали это» |

Эндпоинт баг-трекера может работать так:

  • GET /bugs: список всех багов
  • GET /bugs/42: баг №42
  • POST /bugs: создать новый баг
  • PATCH /bugs/42: обновить статус бага №42
  • DELETE /bugs/42: удалить баг №42

2. URL (адрес)

URL говорит серверу с чем ты работаешь:

https://api.becomeqa.com/v1/users/123/orders

Разбивка:

  • https://api.becomeqa.com: сервер
  • /v1: версия API (частое, но не обязательное)
  • /users/123: конкретный пользователь с ID 123
  • /orders: его заказы

Части после домена называются путём (path). Числа и ID в пути (как 123) называются path-параметрами.

Иногда данные передаются в URL как query-параметры:

GET /users?role=admin&active=true&page=2

Часть ?role=admin&active=true&page=2 фильтрует и пагинирует результаты, не меняя о каком ресурсе идёт речь.

3. Заголовки

Заголовки: метаданные которые отправляются с запросом. В браузере они не видны напрямую, только во вкладке Network. Распространённые:

Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json

Content-Type указывает в каком формате тело запроса, Authorization подтверждает личность (подробнее ниже), а Accept сообщает в каком формате хочешь получить ответ.

4. Тело

Запросы POST, PUT и PATCH обычно включают тело: реальные отправляемые данные. REST API почти всегда используют JSON:

{
  "title": "Кнопка логина не работает на мобильном",
  "severity": "high",
  "steps": ["Открыть приложение на мобильном", "Нажать Login", "Ничего не происходит"]
}

Запросы GET и DELETE обычно без тела.

Анатомия HTTP-ответа

Сервер отвечает тремя частями.

1. Статус-код

Трёхзначное число, которое говорит что произошло:

| Диапазон | Категория | Значение |

|-------|----------|---------|

| 2xx | Успех | Запрос выполнен |

| 3xx | Редирект | Ресурс переехал, иди сюда |

| 4xx | Ошибка клиента | Твой запрос неверен |

| 5xx | Ошибка сервера | Сервер сломался |

Самые важные коды для тестирования:

| Код | Название | Когда появляется |

|------|------|----------------|

| 200 | OK | Стандартный успех для GET |

| 201 | Created | POST, который создал что-то |

| 204 | No Content | Успех, но нечего возвращать (DELETE) |

| 400 | Bad Request | Невалидный ввод (отсутствует поле, неверный формат) |

| 401 | Unauthorized | Не аутентифицирован (нет/плохой токен) |

| 403 | Forbidden | Аутентифицирован, но не разрешено |

| 404 | Not Found | Ресурс не существует |

| 422 | Unprocessable Entity | JSON валидный, но не проходит бизнес-валидацию |

| 429 | Too Many Requests | Превышен лимит запросов |

| 500 | Internal Server Error | Необработанный краш бэкенда |

| 503 | Service Unavailable | Сервер недоступен или перегружен |

2. Заголовки ответа

Аналогично заголовкам запроса: метаданные об ответе.

Content-Type: application/json
X-Request-Id: abc-123-def
Cache-Control: no-cache

3. Тело ответа

Реальные возвращаемые данные, обычно JSON:

{
  "id": 42,
  "title": "Кнопка логина не работает на мобильном",
  "severity": "high",
  "status": "open",
  "created_at": "2026-05-17T10:30:00Z"
}

Или ошибка:

{
  "error": "validation_failed",
  "message": "Title is required",
  "field": "title"
}

Аутентификация: как API знает кто ты

Большинство API требуют аутентификации. Два основных подхода которые ты встретишь.

Bearer Token / JWT

После логина сервер выдаёт токен: длинную строку которая подтверждает личность. Ты включаешь его в каждый последующий запрос:

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEyMywicm9sZSI6ImFkbWluIn0.abc123

Сервер валидирует токен без обращения к базе данных для поиска сессии. Токены истекают (обычно от 15 минут до 24 часов).

Cookie-based сессии

Более старый паттерн. После логина сервер устанавливает куку. Браузер автоматически отправляет её с каждым запросом к этому домену. Ты не видишь её в теле запроса, браузер управляет этим сам.

API-ключи

Используются для межсерверного взаимодействия. Статический ключ в заголовке:

X-API-Key: sk-1234567890abcdef

Как инспектировать API-вызовы в браузере

Открой DevTools, перейди на вкладку Network, отфильтруй по «Fetch/XHR». Все API-вызовы которые делает приложение появятся здесь.

Кликни на любой запрос чтобы увидеть:

  • Вкладка Headers: заголовки запроса, URL, метод
  • Вкладка Payload: тело запроса
  • Вкладка Response: что вернул сервер
  • Статус-код: в виде списка, колонка с числом

Здесь диагностируешь «это баг фронтенда или бэкенда?». Если UI показывает неправильные данные, проверь что API реально вернул. Если API вернул правильные данные, а UI показывает их неправильно, это фронтенд. Если API вернул неправильные данные, это бэкенд.

Тестирование API: что проверять

При тестировании API-эндпоинта (вручную или в Playwright) верифицируй следующее.

Статус-код соответствует ожиданию

  • Создание ресурса: 201, не 200
  • Получение ресурса: 200
  • Успешное удаление без тела: 204
  • Невалидный ввод: 400 или 422, не 500

Тело ответа корректно

  • Обязательные поля присутствуют
  • Типы данных правильные ("age": 25, не "age": "25")
  • Значения совпадают с отправленными
  • Чувствительные данные не утекают (пароли, внутренние ID)

Ошибочные ответы информативны

Ошибки 400 должны объяснять что невалидно. Ошибки 404 должны подтверждать что ресурс не существует. Ошибки 401 не должны раскрывать security-чувствительную информацию.

Граничные случаи ведут себя корректно

  • Пустой список: возвращает [], не null
  • Несуществующий ID: возвращает 404, не 500
  • Невалидный JSON в теле: возвращает 400, не 500
  • Неавторизованное действие: возвращает 403, не 200 с пустым телом

REST API в Playwright

Playwright умеет делать HTTP-запросы напрямую, без браузера:

test('создание пользователя возвращает 201', async ({ request }) => {
  const response = await request.post('https://api.becomeqa.com/users', {
    data: {
      name: 'Test User',
      email: 'test@example.com',
      role: 'member',
    },
  });

  expect(response.status()).toBe(201);

  const body = await response.json();
  expect(body.id).toBeTruthy();
  expect(body.email).toBe('test@example.com');
  expect(body).not.toHaveProperty('password'); // проверяем что пароль не утекает
});

Можно также перехватывать API-вызовы которые делает браузер во время E2E-тестов:

test('приложение корректно обрабатывает ошибку API', async ({ page }) => {
  // Принудительно возвращаем ошибку от API
  await page.route('**/api/users', (route) => {
    route.fulfill({ status: 500, body: JSON.stringify({ error: 'server error' }) });
  });

  await page.goto('/users');

  // Приложение должно показать состояние ошибки, не упасть
  await expect(page.locator('[data-testid="error-banner"]')).toBeVisible();
});

Словарь ключевых терминов

| Термин | Значение |

|------|---------|

| API | Интерфейс для взаимодействия программ |

| REST | Стиль API который использует HTTP |

| Эндпоинт | Конкретная комбинация URL + метод (GET /users) |

| Запрос | То что отправляешь серверу |

| Ответ | То что сервер отправляет обратно |

| Статус-код | Трёхзначное число, успех или ошибка |

| JSON | Формат данных для REST API (текст, пары ключ-значение) |

| Заголовок | Метаданные прикреплённые к запросу или ответу |

| Тело | Реальные данные в запросе или ответе |

| Bearer token | Учётные данные в заголовке Authorization |

| Path-параметр | Переменная часть URL (/users/123, где 123 выступает параметром) |

| Query-параметр | Фильтры в URL после ? (?page=2&sort=asc) |

Понимание REST API делает тебя значительно сильнее как QA-инженера. Читаешь сетевой трафик, диагностируешь где баг: на фронтенде или бэкенде, пишешь API-тесты которые работают в 100 раз быстрее браузерных, и ведёшь намного более предметные разговоры с разработчиками при заведении багов.

→ See also: API-тестирование 101: всё, что нужно знать QA-инженеру в 2026 году | HTTP статус-коды, которые должен знать каждый QA-инженер | API-тестирование в Playwright: выходим за рамки UI | Как работает интернет: объяснение для тестировщиков