Playwright или API: как работает автоотклик
Разбираем, чем браузерная автоматизация откликов отличается от API: сессии, JavaScript, защита от прямых запросов, ресурсы и цена параллельных откликов.
В коде автоотклика есть соблазнительная развилка. Можно сделать один HTTP-запрос и получить компактный JSON, а можно поднять Chromium, дождаться загрузки страницы, найти кнопку и пройти форму. Первый вариант выглядит быстрее и дешевле. Второй — сложнее почти по всем инженерным метрикам.
Но для работных сайтов это не две взаимозаменяемые реализации одной функции. API работает по заранее определённому контракту, а браузер обслуживает живой пользовательский сценарий со сессией, JavaScript, проверками и изменяющимися формами. Поэтому современный автоотклик нельзя свести к замене page.click() на requests.post(). Общая механика сервиса разобрана в полном руководстве по автоотклику на вакансии; здесь разберём именно техническую границу между подходами.
Выбор влияет не только на архитектуру, но и на то, что увидит пользователь. API-клиент может принять успешный сетевой ответ за готовый отклик, хотя площадка вернула дополнительный вопрос. Браузер способен заметить неактивную кнопку, капчу и финальное подтверждение, зато требует ресурсов и постоянной поддержки селекторов. Ниже сравним авторизацию, состояние и рендер, разберём причины 403 у прямых запросов, посчитаем цену параллелизма и переведём всё это в понятные критерии выбора сервиса. После этого обещание «работаем через API» или «используем реальный браузер» можно будет оценить по содержанию, а не по ярлыку.
API и браузер решают разные задачи
API — это отдельный вход в систему. Клиент отправляет запрос на документированный endpoint, передаёт параметры, а сервер возвращает структурированный ответ. Если контракт разрешает действие, не нужно загружать шрифты, строить DOM и ждать анимацию. Поиск двадцати вакансий занимает один запрос, а результат уже разложен по полям.
Браузер идёт по другому пути. Он открывает страницу площадки, получает HTML и JavaScript, хранит cookies, исполняет клиентский код и показывает то же состояние, которое увидел бы человек. Playwright не «скачивает сайт» — он управляет полноценным Chromium и взаимодействует с элементами после рендера.
Разница видна на простом сравнении:
| API-запрос | Playwright в Chromium | |
|---|---|---|
| Авторизация | Токен и права приложения | Пользовательская сессия и cookies |
| Данные | Готовый JSON по контракту | HTML, DOM и состояние интерфейса |
| JavaScript | Не исполняется | Исполняется как в обычном браузере |
| Форма отклика | Только если есть подходящий метод | Проход по фактическим шагам формы |
| Изменения | Версионирование или обновление документации | Селекторы и сценарий могут измениться сразу |
| Цена одного действия | Низкая | Выше: память, CPU, сеть и время рендера |
| Неожиданный ручной шаг | Обычно ошибка API | Можно показать пользователю окно и продолжить вручную |
У API есть преимущество там, где площадка действительно предоставляет стабильный контракт. У браузера — там, где важен весь интерфейс, а не одна операция. Попытка притвориться API-клиентом через внутренние запросы сайта получает недостатки обоих подходов: контракт не документирован, а состояние браузера всё равно приходится воспроизводить вручную.
Почему requests и curl не заменяют браузерную сессию
В официальной документации API работных сайтов по-прежнему описаны вакансии, резюме и отклики. Из этого легко сделать неверный вывод: достаточно скопировать URL в curl, добавить User-Agent и получить те же данные, что видны на сайте.
На практике доступ проходит через несколько независимых слоёв. Endpoint сначала видит IP и заголовки клиента, затем защиту от автоматических запросов, авторизацию и права конкретного приложения или пользователя. Только после этого выполняется бизнес-метод. Ответ 403 Forbidden на первом слое ничего не говорит о том, правильно ли собраны параметры поиска: до них запрос мог вообще не дойти.
Именно это происходит с прямым серверным поиском JobTurbo. В коде сохранился API-путь, но запросы с серверных адресов стабильно получают 403 от защитного слоя. Свежие браузерные cookies иногда дают больше контекста, однако не превращают API в надёжный основной канал. Поэтому рабочая схема быстро переключается на поиск через страницу, не заставляя пользователя ждать несколько повторов заведомо закрытого запроса.
С откликом проблема ещё шире. Между вакансией и кнопкой «Отправить» могут появиться обязательное сопроводительное, вопрос работодателя, тест, подтверждение телефона или капча. Один POST-запрос должен заранее знать весь набор полей и внутренние идентификаторы текущей формы. Браузер видит их после рендера и может принять решение по фактическому состоянию.
Не путать с обратным проектированием фронтенда. В DevTools действительно можно увидеть внутренний fetch, который отправляет форма. Но этот URL не становится публичным API: он может зависеть от CSRF-токена, одноразового состояния, cookies и версии интерфейса. Площадка вправе поменять его без миграционного периода, потому что единственный официальный клиент такого запроса — собственная страница.
Что даёт рендер JavaScript
Современная страница — это не готовый документ с кнопкой. Сервер отдаёт каркас, затем клиентский код загружает данные, выбирает вариант интерфейса и меняет доступность элементов. Кнопка может существовать в HTML, но оставаться неактивной, пока не заполнено обязательное поле. Текст ошибки может появиться только после попытки перейти дальше.
Playwright ждёт не строку в ответе, а наблюдаемое состояние:
- Страница открылась и не перекинула на логин.
- Карточка вакансии отрисовалась.
- Кнопка отклика видима и доступна.
- Форма приняла сопроводительное и обязательные ответы.
- После отправки появился признак успешного отклика.
Последний пункт особенно важен. HTTP 200 означает лишь успешную обработку сетевого запроса. Он не всегда равен отправленному отклику: сервер мог вернуть новую форму, предупреждение или страницу проверки. В браузерном сценарии подтверждением служит изменившийся интерфейс — например, статус «Вы откликнулись». Если подтверждения нет, результат нельзя записывать как успех.
Тот же принцип нужен для капчи. Автоматизация не должна пытаться «продавить» страницу. Она останавливается, показывает видимое окно пользователю и продолжает только после ручного решения. Это медленнее идеального API-вызова, но честнее ложного успешного статуса.
Цена браузерного подхода
Chromium заметно тяжелее HTTP-клиента. Один контекст держит движок JavaScript, DOM, сетевой кэш и состояние вкладок. Если бездумно запустить по браузеру на каждый отклик, закончится память, а десятки одновременных страниц создадут неестественный всплеск действий.
Поэтому масштабируется не число процессов, а очередь:
- один авторизованный контекст переиспользуется для последовательных вакансий;
- параллелизм ограничивается ресурсами сервера, а не размером списка;
- между действиями есть паузы, чтобы страница успевала закончить переход;
- при росте CPU или памяти новые задачи ждут свободного слота;
- ошибки формы классифицируются отдельно от истёкшей сессии и капчи.
Для пользователя из этого следует полезное ограничение: браузерный автоотклик не должен обещать тысячу заявок за минуту. Такая цифра означает либо пустые API-вызовы, либо десятки одновременно открытых сессий без контроля. В поиске работы скорость важна на уровне часов, а не миллисекунд. Гораздо важнее успевать отвечать на приглашения и не расходовать отклики на нерелевантные вакансии. Практический выбор темпа есть в разборе количества откликов в день.
Вторая цена — сопровождение. API-контракт меняется заметно и обычно документируется. DOM может поменяться после эксперимента интерфейса: текст кнопки, структура модалки или атрибут элемента станут другими для части пользователей. Поэтому браузерный движок нуждается в наборах селекторов, тестовых HTML-фикстурах и живых проверках без финальной отправки.
Как JobTurbo использует Playwright
JobTurbo хранит не «секретный API площадки», а состояние браузерной сессии. Пользователь входит на площадку сам, после чего Playwright открывает поиск и вакансии в авторизованном контексте. Для серверных запусков работа идёт с российских адресов; в десктоп-приложении — с компьютера и подключения самого пользователя.
Дальше задачи разделены:
- браузер читает выдачу, открывает карточку и проходит фактическую форму;
- фильтры проверяют должность, регион, формат работы, зарплату и исключения до отклика;
- AI формирует письмо из текста вакансии и резюме, а не из одного шаблона;
- движок подтверждает результат по состоянию страницы и отдельно сообщает ручные шаги;
- ограничитель нагрузки не запускает больше Chromium-контекстов, чем выдерживает текущий хост.
Посмотреть этот путь без технических деталей можно на странице «Как работает JobTurbo». А почему персональное письмо остаётся важным даже при исправной автоматизации, разобрано в руководстве по AI-сопроводительным.
Важно: Playwright не даёт иммунитета от правил площадки. Он нужен не для обхода ограничений, а для корректной работы через реальный интерфейс. Если площадка возвращает лимит, требует подтверждение или меняет форму, правильная реакция — остановиться и показать причину, а не маскировать ошибку повторными кликами.
Итог
API выигрывает там, где есть доступный и достаточный официальный контракт. Playwright выигрывает там, где результат зависит от живой сессии, JavaScript и формы, которую нужно пройти до видимого подтверждения.
На работном сайте прямой curl может закончиться на 403 ещё до поиска, а один внутренний POST не покрывает вопросы работодателя, тесты и капчу. Поэтому браузерный подход дороже по ресурсам и сопровождению, но даёт главное: автоматизация видит то же состояние, что пользователь, и не записывает незавершённый отклик как успешный.
Частые вопросы
Чем Playwright отличается от API площадки?
API возвращает структурированные данные по HTTP и требует соблюдать правила конкретного метода. Playwright управляет браузером: загружает страницу, исполняет JavaScript и работает внутри пользовательской сессии с её cookies.
Почему прямой запрос к API площадки через curl возвращает 403?
Сам URL и правильный User-Agent не гарантируют доступ. Прямой запрос может остановить защитный слой площадки по IP, состоянию сессии или другим сигналам; в такой ситуации повторение того же curl-запроса не превращает его в браузерную сессию.
Значит ли это, что API площадок больше не существует?
Нет. Документация и часть методов существуют, особенно для работодателей и интеграций. Но наличие метода в документации не означает, что анонимный серверный запрос подходит для полного кандидатского сценария от поиска до отправки отклика.
Можно ли отправлять отклики обычными requests-запросами?
Надёжно воспроизвести весь сценарий одними requests-запросами нельзя: отклик зависит от авторизации, состояния страницы, обязательных полей, тестов и защитных проверок. Незадокументированные внутренние запросы фронтенда также могут меняться без предупреждения.
Playwright всегда медленнее API?
Один HTTP-запрос дешевле загрузки страницы, но сравнивать нужно весь сценарий. Браузер тратит больше CPU и памяти, зато проходит тот же интерфейс, видит валидацию формы и может корректно остановиться на ручном шаге.
Защищает ли реальный браузер от ограничений площадки?
Нет. Браузерная автоматизация не отменяет правила и ограничения площадки. Она лишь работает через тот же интерфейс, что и пользователь; релевантность, умеренный темп и корректная обработка капчи всё равно обязательны.
Запустите автоотклик бесплатно
До 25 успешных откликов за скользящие 24 часа — без оплаты и привязки карты. AI подготовит сопроводительное под каждую подходящую вакансию.
Подключить JobTurbo →