Socks5Proxy

Selenium 프록시 설정, Chrome과 Firefox에 SOCKS5·HTTP 프록시 연결하기

이 가이드는 Selenium 4로 Chrome과 Firefox를 실행할 때 Socks5Proxy의 HTTP 프록시와 SOCKS5 프록시를 연결하는 방법과, Chrome 실행 인자가 프록시 비밀번호를 받지 않아 IP 인증을 쓰는 설정을 설명해요.

Selenium에서 프록시 인증이 어려운 이유는 무엇인가요?

Chrome은 --proxy-server 실행 인자로 프록시 주소를 받지만, 그 주소 안의 아이디와 비밀번호는 받지 않아요. 아이디와 비밀번호가 필요한 프록시에 연결하면 브라우저가 인증 창을 띄우는데, Selenium으로는 이 창에 값을 넣기 어려워요.

가장 깔끔한 해결은 IP 인증이에요. 대시보드에 Selenium이 실행되는 서버나 PC의 IPv4를 등록하면 프록시가 그 IP의 연결을 아이디와 비밀번호 없이 받아요. 그러면 Chrome에는 ip:port만 넣으면 돼요. 최대 10개 IP를 등록할 수 있어 여러 서버에서 함께 쓸 수 있어요.

예시는 IP 198.51.100.23, HTTP 포트 8000, SOCKS5 포트 1080을 써요.

pip install selenium

Chrome에 HTTP 프록시를 연결하려면 어떻게 하나요?

IP 인증을 등록한 뒤 ChromeOptions에 --proxy-server 인자로 주소를 넣어요. Selenium 4.6 이상은 Selenium Manager가 맞는 chromedriver를 자동으로 받아서 따로 설치할 필요가 없어요.

headless 모드에서도 같은 인자가 그대로 적용돼요. 연결 확인은 IP 확인 주소를 열어 화면의 IP가 프록시 IP인지 보면 돼요.

from selenium import webdriver
from selenium.webdriver.common.by import By

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")  # this machine's IP is authorized in the dashboard
opts.add_argument("--headless=new")

driver = webdriver.Chrome(options=opts)
try:
    driver.get("https://api.ipify.org")
    print(driver.find_element(By.TAG_NAME, "body").text)  # should print the proxy IP
finally:
    driver.quit()

Chrome에서 SOCKS5 프록시는 어떻게 쓰나요?

--proxy-server에 socks5:// 주소를 넣으면 돼요. Chrome은 SOCKS5를 쓸 때 도메인 이름 확인을 프록시 쪽에서 하지만, 일부 환경에서는 내부 DNS 확인이 남을 수 있어서 --host-resolver-rules 인자로 로컬 이름 확인을 막아 두는 방법이 많이 쓰여요.

SOCKS5도 IP 인증으로 연결해요. Chrome은 SOCKS 프록시의 아이디와 비밀번호 인증을 지원하지 않기 때문이에요.

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=socks5://198.51.100.23:1080")
# make sure host names are resolved through the proxy
opts.add_argument('--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE 198.51.100.23')

driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

Firefox에는 어떻게 연결하나요?

Firefox는 환경 설정 값으로 프록시를 지정해요. network.proxy.type을 1(수동)로 두고 HTTP 또는 SOCKS 주소와 포트를 넣어요. SOCKS5는 network.proxy.socks_version을 5로, network.proxy.socks_remote_dns를 True로 두면 프록시 쪽에서 이름을 확인해요.

Firefox도 실행 설정으로 프록시 비밀번호를 넣는 방법이 없어서 IP 인증을 쓰는 것이 가장 간단해요.

from selenium import webdriver

opts = webdriver.FirefoxOptions()
opts.set_preference("network.proxy.type", 1)
opts.set_preference("network.proxy.socks", "198.51.100.23")
opts.set_preference("network.proxy.socks_port", 1080)
opts.set_preference("network.proxy.socks_version", 5)
opts.set_preference("network.proxy.socks_remote_dns", True)

driver = webdriver.Firefox(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

여러 브라우저를 다른 IP로 동시에 띄우려면 어떻게 하나요?

브라우저마다 다른 프록시 주소를 넣어 따로 실행하면 돼요. 아래 코드는 API로 ip:port 목록을 받아 브라우저 3개를 서로 다른 IP로 띄우는 예시예요. 브라우저 하나가 메모리를 많이 쓰니 서버 크기에 맞춰 동시에 띄울 개수를 정하세요.

로그인 세션처럼 브라우저를 오래 쓰는 작업은 브라우저 하나에 IP 하나를 고정하고, 작업이 끝날 때까지 바꾸지 않는 것이 좋아요.

import requests
from selenium import webdriver

KEY = "YOUR_API_KEY"
lines = requests.get(
    "https://socks5proxy.io/api/v1/proxies/download",
    params={"format": "ip:port", "protocol": "http"},
    headers={"Authorization": "Bearer " + KEY},
    timeout=30,
).text.split()

drivers = []
for line in lines[:3]:
    opts = webdriver.ChromeOptions()
    opts.add_argument("--headless=new")
    opts.add_argument("--proxy-server=http://" + line)
    drivers.append(webdriver.Chrome(options=opts))

for d in drivers:
    d.get("https://api.ipify.org")
    print(d.page_source)
    d.quit()

아이디·비밀번호 인증을 꼭 써야 한다면 어떻게 하나요?

IP 인증을 쓸 수 없는 환경, 예를 들어 나가는 IP가 계속 바뀌는 환경이라면 두 가지 방법이 있어요. 첫째는 selenium-wire 같은 중간 프록시 라이브러리로 인증 정보를 대신 넣는 방법이고, 둘째는 같은 서버에서 인증 없는 로컬 중계 프록시를 띄워 Chrome은 로컬 주소로, 로컬 중계는 아이디·비밀번호로 Socks5Proxy에 연결하게 하는 방법이에요.

두 방법 모두 구성 요소가 하나 늘어나서 관리할 것이 많아져요. 가능하다면 고정 IP 서버에서 IP 인증을 쓰는 것이 가장 단순하고 빨라요.

브라우저 환경을 그 나라에 맞추려면 무엇을 설정하나요?

IP 나라에 맞춰 Chrome의 --lang 인자와 Accept-Language 설정을 바꾸면 페이지가 그 나라 언어로 열려요. 시간대가 중요한 사이트라면 CDP 명령 Emulation.setTimezoneOverride로 시간대도 맞출 수 있어요.

창 크기는 --window-size 인자로 정하고, 휴대폰 화면이 필요하면 모바일 기기 흉내 설정을 쓰세요. 이런 값을 나라별 설정 묶음으로 만들어 두면 같은 시험을 여러 나라에서 일정하게 돌릴 수 있어요.

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")
opts.add_argument("--lang=de-DE")
opts.add_argument("--window-size=1366,900")

driver = webdriver.Chrome(options=opts)
driver.execute_cdp_cmd("Emulation.setTimezoneOverride", {"timezoneId": "Europe/Berlin"})
driver.get("https://example.com/")
driver.quit()

Selenium Grid나 원격 브라우저에서도 같은 설정을 쓰나요?

네. ChromeOptions와 FirefoxOptions는 원격 실행에서도 그대로 넘어가요. webdriver.Remote에 같은 옵션을 넣으면 Grid 노드의 브라우저가 그 프록시로 접속해요. 이때 IP 인증에 등록할 IP는 코드를 실행하는 PC가 아니라 브라우저가 실제로 실행되는 Grid 노드의 나가는 IP예요.

노드가 여러 대라면 각 노드의 IP를 모두 등록하세요. 최대 10개까지 등록할 수 있어요. 클라우드 노드가 자주 바뀌는 환경이라면 노드에 고정 IP를 붙이는 것이 관리하기 편해요.

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")  # authorize the Grid node IP, not this machine
driver = webdriver.Remote(command_executor="http://grid.example.internal:4444", options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

연결이 안 될 때는 무엇을 확인하나요?

ERR_PROXY_CONNECTION_FAILED는 주소나 포트가 틀린 경우가 많아요. HTTP 주소에 SOCKS5 포트를 넣지 않았는지 확인하세요. ERR_TUNNEL_CONNECTION_FAILED가 나거나 인증 창이 뜨면 IP 인증에 등록한 IP와 실제로 나가는 IP가 다른 경우예요. 서버에서 cURL로 api.ipify.org를 프록시 없이 열어 나가는 IP를 확인하고 그 값을 등록해 주세요.

클라우드 서버는 재시작하면 나가는 IP가 바뀔 수 있어요. 고정 IP를 쓰거나, IP가 바뀔 때 대시보드의 등록 목록도 함께 바꿔 주세요.

Selenium 프록시 설정, Chrome·Firefox 연결 방법 | Socks5Proxy