# Аутентификация прокси в nodriver: три работающих решения

Первый результат по запросу аутентификации прокси в nodriver — обсуждение на GitHub, а не руководство. У nodriver нет встроенной поддержки user:pass — вот три работающих решения и однострочный ярлык, который многие упускают.

Поиск **аутентификация прокси в nodriver** и первые десять результатов — обсуждение на GitHub, демонстрационный репозиторий, несколько тем на Stack Overflow о другой библиотеке и один пост на Reddit — никакого реального руководства. Причина проста: nodriver, асинхронный CDP-преемник undetected-chromedriver (у этого проекта 12.8k звезд на GitHub и 1.3k форков), не имеет встроенного способа передачи `user:pass` прокси. Chrome игнорирует учетные данные, встроенные в флаг командной строки, и nodriver не исправляет это. Это руководство — та страница, в которую должно было превратиться обсуждение: что работает, что нет и три решения, которые позволяют запустить аутентифицированный прокси.

## Простой прокси работает; аутентифицированный прокси — нет

Неаутентифицированный прокси — это однострочная команда. Передайте адрес через `browser_args`, и каждый запрос будет выходить с IP прокси:

```python
import nodriver as uc

async def main():
    browser = await uc.start(
        browser_args=["--proxy-server=residentialboson.quantumproxies.io:PORT"],
    )
    page = await browser.get("https://httpbin.org/ip")
    print(await page.get_content())   # shows the proxy exit IP

uc.loop().run_until_complete(main())
```

Теперь добавьте учетные данные — `--proxy-server=http://USER:PASS@host:port` — и это ломается. Chromium удаляет сегмент `USER:PASS@`, так как формат флага не предусматривает слот для учетных данных, затем прокси отвечает `407 Proxy Authentication Required`, и Chrome вызывает нативный диалог входа, который находится вне DOM. nodriver не может его увидеть или заполнить. Этот 407 — та же стена, описанная в [нашем руководстве по исправлению ошибок 407](https://quantumproxies.io/blog/fix-407-proxy-authentication-required): прокси отвергает вас, а не браузер. Поэтому каждое реальное решение должно отвечать на вызов другим способом.

## Решение 1: белый список IP — без учетных данных, без диалога

Это тот ярлык, о котором никогда не упоминают в обсуждениях на GitHub, и это самое простое решение. Если ваш скрейпер работает с машины со стабильным публичным IP, зарегистрируйте этот IP в панели управления вашего провайдера и полностью откажитесь от учетных данных — шлюз аутентифицирует вас по исходному адресу. Код nodriver остается простым фрагментом `--proxy-server` выше, без кода аутентификации. Каждый план QuantumProxies поддерживает белый список IP наряду с user:pass на своих [резидентных прокси](https://quantumproxies.io/residential-proxies), поэтому это рекомендуемый путь, когда ваш выходной IP фиксирован. Его единственное ограничение — топологическое: он аутентифицирует машину, а не скрипт, поэтому эфемерные облачные раннеры, контейнеры за NAT и CI-боксы с изменяющимися IP нуждаются в одном из следующих двух решений.

![Четыре способа аутентифицировать прокси nodriver на шлюзе: белый список IP, обработчик аутентификации CDP Fetch, сгенерированное расширение Chrome и локальный релей. Карточка объясняет, когда подходит каждый: белый список не требует кода при фиксированном IP, обработчик и расширение отвечают на запрос, когда IP меняется, а релей покрывает SOCKS5.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785776549/blog/generated/qp-b10-001-diag1.png)
*Белый список не требует кода, когда ваш IP фиксирован; обработчик CDP и расширение отвечают на вызов учетных данных, когда это не так.*

## Решение 2: ответ на вызов с помощью обработчика CDP Fetch

nodriver напрямую использует протокол Chrome DevTools, поэтому вы можете перехватить вызов аутентификации в процессе — файл расширения не нужен. Включите домен `Fetch` с `handle_auth_requests=True`, затем ответьте на каждое событие `AuthRequired` с помощью `continue_with_auth`. Две детали, обе из ответа в обсуждении #1798, являются разницей между работающим и зависающим:

- **Зарегистрируйте обработчики до включения домена.** Внутренний вызов `enable` в nodriver переопределяет вашу регистрацию обработчиков, поэтому если вы добавите их позже, события никогда не сработают — это причина номер один, по которой люди сообщают 'ничего не происходит'.
- **Отправляйте ответы без ожидания.** Ожидание ответа внутри обработчика блокирует цикл событий и приводит к взаимоблокировке всего браузера. Оберните каждую отправку в `asyncio.create_task`, чтобы она выполнялась без блокировки.

```python
import asyncio
import nodriver as uc

PROXY = "residentialpremium.quantumproxies.io:8080"   # host:port for --proxy-server
USER, PASS = "USER", "PASS"

class Scraper:
    def __init__(self):
        uc.loop().run_until_complete(self.run())

    async def run(self):
        browser = await uc.start(browser_args=[f"--proxy-server={PROXY}"])
        self.tab = await browser.get("data:,")        # blank tab first

        # 1) handlers BEFORE enabling the Fetch domain
        self.tab.add_handler(uc.cdp.fetch.RequestPaused, self.on_request)
        self.tab.add_handler(uc.cdp.fetch.AuthRequired, self.on_auth)
        # 2) only now turn on interception with auth handling
        await self.tab.send(uc.cdp.fetch.enable(handle_auth_requests=True))

        page = await browser.get("https://httpbin.org/ip")
        await asyncio.sleep(3)
        print(await page.get_content())

    async def on_auth(self, event):
        # fire-and-forget: awaiting here deadlocks the loop
        asyncio.create_task(self.tab.send(uc.cdp.fetch.continue_with_auth(
            request_id=event.request_id,
            auth_challenge_response=uc.cdp.fetch.AuthChallengeResponse(
                response="ProvideCredentials", username=USER, password=PASS,
            ),
        )))

    async def on_request(self, event):
        asyncio.create_task(self.tab.send(
            uc.cdp.fetch.continue_request(request_id=event.request_id)))

if __name__ == "__main__":
    Scraper()
```

Одна оговорка, всплывшая в той же теме: пользователь обнаружил, что это работало на простых HTTP-страницах, но не на HTTPS, и виновником был низкокачественный прокси, а не код — переход на лучший выход это исправил. Это повторяющийся урок скрытого скрейпинга: обработчик отвечает на вызов, но репутация IP решает, пустит ли вас сайт.

## Решение 3: сгенерированное расширение Chrome

Другой шаблон сообщества создает небольшое расширение Chrome при запуске, которое как устанавливает прокси, так и отвечает на вызов учетных данных через `chrome.webRequest.onAuthRequired` — тот же трюк, который работает в Selenium и Puppeteer. Вы пишете небольшой манифест и фоновый рабочий процесс в временный каталог и загружаете его через `--load-extension`:

```python
import nodriver as uc

async def main():
    # ext_dir holds a Manifest V3 extension: manifest.json + worker.js that
    # calls chrome.proxy.settings.set(...) and returns authCredentials from
    # chrome.webRequest.onAuthRequired. Generate it once, then load it:
    browser = await uc.start(browser_args=[
        "--load-extension=" + ext_dir,
        "--headless=new",   # extensions only load in the NEW headless mode
    ])
    page = await browser.get("https://httpbin.org/ip")
    print(await page.get_content())

uc.loop().run_until_complete(main())
```

Полный манифест и рабочий процесс идентичны файлам Manifest V3 в нашем [руководстве по аутентификации прокси в Selenium](https://quantumproxies.io/blog/selenium-proxy-setup-authenticated) — скопируйте их дословно, меняется только вызов запуска. Две подводные камни повторяются везде: расширения загружаются только под `--headless=new` (простой `--headless` не работает), и распакованный каталог более надежен в разных версиях Chrome, чем упакованный zip. Расширение обрабатывает любой тип прокси, что делает его запасным вариантом, когда маршрут CDP сражается с вами.

## Четвертый вариант: локальный релей

Если вы предпочитаете вообще не трогать nodriver, запустите небольшой локальный релей, который хранит учетные данные и предоставляет конечную точку без аутентификации на `127.0.0.1`. nodriver затем указывает на адрес обратной связи с простым флагом и никогда не видит вызова. Это самый чистый путь для SOCKS5, где Chromium категорически отказывается от аутентифицированных прокси (отслеживается как ошибка Chromium 40829748). Мы рассматриваем минимальный релей, готовые инструменты и когда это излишне в [руководстве по релею прокси](https://quantumproxies.io/blog/proxy-relay-socks5-auth-tools).

## Примечание о SOCKS5

Неаутентифицированный SOCKS5 работает через флаг — `--proxy-server=socks5://host:port` — но аутентифицированный SOCKS5 не работает, и никакой обработчик CDP вас не спасет, потому что Chromium никогда не поддерживал аутентификацию SOCKS5 с именем пользователя и паролем. Практические ответы те же три: включите IP в белый список, запустите релей, или используйте HTTP-эндпоинт провайдера. Каждый план QuantumProxies предоставляет как HTTP, так и [SOCKS5 прокси](https://quantumproxies.io/socks5-proxies) на одном шлюзе, поэтому переключение на HTTP-эндпоинт часто является самым быстрым решением для SOCKS5. Для браузеров с антидетектом как семейства, [карта аутентифицированных прокси](https://quantumproxies.io/blog/anti-detect-frameworks-authenticated-proxies-map) сравнивает nodriver, zendriver и остальные бок о бок.

![Белый список IP для nodriver: зарегистрируйте исходящий IP машины у провайдера, запускайте с простым флагом --proxy-server, и шлюз аутентифицирует адрес источника, поэтому не появляются ни 407, ни диалог учетных данных. Карточка показывает ноль кода аутентификации: подходит для фиксированного VPS, но не для CI-раннеров за NAT.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785776549/blog/generated/qp-b10-001-diag2.png)
*Когда выходной IP стабилен, белый список аутентифицирует машину, и код аутентификации полностью исчезает.*

## Часто задаваемые вопросы

### Поддерживает ли nodriver аутентифицированные прокси?

Не нативно. Вы можете передать неаутентифицированный прокси через `browser_args=["--proxy-server=host:port"]`, но `user:pass` в этом флаге удаляется Chromium. Чтобы аутентифицироваться, вы либо включаете IP в белый список у провайдера, отвечаете на вызов с помощью обработчика CDP `Fetch.AuthRequired`, генерируете расширение Chrome для аутентификации прокси, либо запускаете локальный релей, который хранит учетные данные.

### Почему мой обработчик аутентификации в nodriver не получает событий?

Почти всегда потому, что вы включили домен `Fetch` до регистрации обработчиков. Внутренний `enable` в nodriver переопределяет регистрацию, поэтому события никогда не достигают вашего обратного вызова. Сначала добавьте обработчики `RequestPaused` и `AuthRequired`, затем вызовите `fetch.enable(handle_auth_requests=True)`. Также оберните свои ответы в `asyncio.create_task`, чтобы ожидание их не могло блокировать цикл.

### Может ли nodriver использовать SOCKS5 прокси с именем пользователя и паролем?

Нет. Chromium не поддерживает аутентифицированный SOCKS5 (ошибка Chromium 40829748), и nodriver наследует это ограничение. Неаутентифицированный SOCKS5 работает через `--proxy-server=socks5://host:port`. Для аутентифицированного SOCKS5 включите IP в белый список, запустите локальный релей, который добавляет учетные данные, или переключитесь на HTTP-эндпоинт провайдера, который чисто обрабатывает Basic auth.

### nodriver или zendriver для аутентифицированных прокси?

Оба имеют тот же пробел и те же решения, потому что zendriver — это форк сообщества nodriver. У zendriver более активный трекер проблем, где вопрос аутентификации открыто обсуждается, но рабочие методы идентичны. Если вы используете форк, настройка, специфичная для форка, зеркально отражает все здесь — обработчик CDP и белый список работают одинаково.

Честное резюме: nodriver не будет выполнять аутентификацию прокси за вас, и это нормально, когда вы знаете карту. Используйте белый список, когда ваш IP стабилен, обращайтесь к обработчику CDP или расширению, когда это не так, и держите релей в запасе для SOCKS5. Код выше отвечает на вызов — но чистый резидентный выход — это то, что действительно позволяет вам пройти через дверь.

[Запустите nodriver на резидентных IP в белом списке](https://quantumproxies.io/residential-proxies)
