Socks5Proxy

Playwright 프록시 설정, 브라우저와 컨텍스트마다 다른 IP 연결하기

이 가이드는 Playwright의 proxy 옵션에 Socks5Proxy의 HTTP 프록시와 SOCKS5 프록시를 server, username, password로 연결하는 방법과, 브라우저 하나에서 컨텍스트마다 다른 IP를 쓰는 방법을 Node.js와 Python 코드로 설명해요.

Playwright의 프록시 설정은 무엇이 편한가요?

Playwright는 프록시 주소와 아이디, 비밀번호를 하나의 proxy 옵션으로 받아서 인증 창 처리를 따로 할 필요가 없어요. Chromium, Firefox, WebKit 세 브라우저 모두 같은 옵션을 써요.

또 브라우저를 하나만 실행하고 그 안에 여러 컨텍스트를 만들 때 컨텍스트마다 다른 프록시를 줄 수 있어요. 컨텍스트는 쿠키와 저장소가 분리된 별도 프로필이라서, 브라우저 하나로 여러 IP와 여러 세션을 함께 다룰 수 있어 메모리를 아낄 수 있어요.

예시는 IP 198.51.100.23, HTTP 포트 8000, SOCKS5 포트 1080, 아이디 spx_user, 비밀번호 spx_pass를 써요.

npm install playwright
npx playwright install chromium

브라우저 전체에 HTTP 프록시를 연결하려면 어떻게 하나요?

launch의 proxy 옵션에 server, username, password를 넣으면 그 브라우저의 모든 페이지가 같은 프록시를 써요. HTTPS 사이트는 CONNECT 터널로 암호화된 채 전달돼요.

import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "http://198.51.100.23:8000", username: "spx_user", password: "spx_pass" },
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.textContent("body")); // proxy IP
await browser.close();

컨텍스트마다 다른 IP를 쓰려면 어떻게 하나요?

newContext에 proxy 옵션을 넣으면 그 컨텍스트만 그 프록시를 써요. 아래 코드는 API로 목록을 받아 컨텍스트 3개를 서로 다른 IP로 만들고 각 컨텍스트에서 보이는 IP를 출력해요. 계정 여러 개를 동시에 다루는 작업에서는 컨텍스트 하나에 계정 하나와 IP 하나를 짝지어 두면 돼요.

Chromium 일부 버전과 Windows 환경에서는 컨텍스트별 프록시를 쓰려면 launch에도 proxy 옵션이 있어야 하는 경우가 있었어요. 그럴 때는 launch에 첫 번째 프록시를 넣고 컨텍스트마다 덮어쓰면 돼요.

import { chromium } from "playwright";

const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies/download?format=ip:port:user:pass&protocol=http", {
  headers: { Authorization: "Bearer " + KEY },
});
const lines = (await res.text()).trim().split("\n").slice(0, 3);

const browser = await chromium.launch();
for (const line of lines) {
  const [ip, port, user, pass] = line.trim().split(":");
  const context = await browser.newContext({
    proxy: { server: "http://" + ip + ":" + port, username: user, password: pass },
    locale: "en-US",
  });
  const page = await context.newPage();
  await page.goto("https://api.ipify.org");
  console.log(ip, await page.textContent("body"));
  await context.close();
}
await browser.close();

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

server에 socks5:// 주소를 넣으면 돼요. Chromium은 SOCKS5 프록시의 아이디·비밀번호 인증을 지원하지 않아서 SOCKS5는 IP 인증으로 연결하는 것을 추천해요. 대시보드에 실행 서버의 IPv4를 등록하고 username, password 없이 server만 넣으세요.

아이디와 비밀번호로 연결해야 한다면 같은 IP의 HTTP 포트를 쓰면 돼요. 대상 사이트에서 보이는 IP와 위치는 같아요.

import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "socks5://198.51.100.23:1080" }, // server IP is authorized in the dashboard
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.textContent("body"));
await browser.close();

Python에서는 어떻게 쓰나요?

Python용 Playwright도 같은 구조예요. proxy 사전에 server, username, password를 넣어요. 동기 방식 예시를 아래에 두었어요. 비동기 방식도 옵션 이름은 같아요.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://198.51.100.23:8000",
        "username": "spx_user",
        "password": "spx_pass",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.text_content("body"))
    browser.close()

결과를 그 나라 이용자처럼 보이게 하려면 무엇을 맞추나요?

IP 나라에 맞춰 컨텍스트의 locale과 timezoneId를 함께 정하면 페이지가 그 나라 이용자에게 보이는 언어와 시간으로 그려져요. 예를 들어 독일 IP라면 locale de-DE, timezoneId Europe/Berlin을 쓰면 돼요.

그림과 동영상이 필요 없다면 page.route로 해당 요청을 막아 대역폭과 시간을 아낄 수 있어요. 공유 플랜은 월 대역폭이 정해져 있어서 특히 도움이 돼요.

  • locale과 timezoneId를 IP 나라에 맞추기
  • 컨텍스트 하나에 계정 하나, IP 하나
  • 필요 없는 그림·동영상 요청은 page.route로 막기
  • SOCKS5는 IP 인증, 아이디·비밀번호는 HTTP 포트

목록을 자동으로 받아 작업마다 나눠 쓰려면 어떻게 하나요?

API의 GET /proxies는 JSON으로 줄마다 IP, 포트, 나라를 돌려줘요. 나라 조건을 넣어 받으면 나라별 작업에 맞는 목록을 바로 만들 수 있어요. 아래 코드는 미국 프록시만 받아 작업 수만큼 컨텍스트를 만드는 예시예요. 응답 칸 이름은 API 문서에서 확인할 수 있어요.

작업이 많다면 컨텍스트를 끝까지 열어 두지 말고, 작업이 끝날 때마다 닫아 메모리를 돌려주세요.

import { chromium } from "playwright";

const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies?country=us&protocol=http", {
  headers: { Authorization: "Bearer " + KEY },
});
const { proxies } = await res.json();

const browser = await chromium.launch();
for (const p of proxies.slice(0, 5)) {
  const context = await browser.newContext({
    proxy: { server: "http://" + p.host + ":" + p.http_port, username: p.username, password: p.password },
    locale: "en-US",
    timezoneId: "America/New_York",
  });
  const page = await context.newPage();
  await page.goto("https://api.ipify.org");
  console.log(await page.textContent("body"));
  await context.close();
}
await browser.close();

필요 없는 요청을 막아 대역폭을 아끼려면 어떻게 하나요?

page.route나 context.route로 그림, 글꼴, 동영상 요청을 막으면 페이지가 빨리 열리고 프록시 대역폭도 아낄 수 있어요. 데이터만 필요한 수집 작업에서 특히 효과가 커요.

await context.route("**/*", (route) => {
  const type = route.request().resourceType();
  return ["image", "font", "media"].includes(type) ? route.abort() : route.continue();
});

Firefox와 WebKit에서도 같은 프록시를 쓰나요?

네. Playwright는 세 브라우저 모두 같은 proxy 옵션을 받아요. 시험 팀이라면 같은 프록시로 Chromium, Firefox, WebKit을 차례로 띄워 나라별 화면이 브라우저마다 같은지 확인할 수 있어요.

Firefox는 SOCKS5 아이디·비밀번호 인증이 브라우저에서 지원되지 않는 점이 Chromium과 같아서, SOCKS5는 IP 인증으로 연결해 주세요. HTTP 포트는 세 브라우저 모두 아이디와 비밀번호로 연결돼요.

Playwright Test를 쓴다면 playwright.config의 use 항목에 proxy를 넣어 모든 시험에 적용하거나, 프로젝트를 나라별로 나눠 각각 다른 프록시를 줄 수 있어요.

import { defineConfig } from "@playwright/test";

export default defineConfig({
  projects: [
    { name: "us", use: { locale: "en-US", proxy: { server: "http://198.51.100.23:8000", username: "spx_user", password: "spx_pass" } } },
    { name: "de", use: { locale: "de-DE", proxy: { server: "http://198.51.100.24:8000", username: "spx_user", password: "spx_pass" } } },
  ],
});

자주 나는 오류는 어떻게 해결하나요?

net::ERR_PROXY_CONNECTION_FAILED는 server 주소나 포트가 틀린 경우예요. 407 또는 인증 관련 오류는 username과 password 값을 확인하세요. Browser does not support socks5 proxy authentication 오류는 SOCKS5에 아이디와 비밀번호를 넣었을 때 나요. IP 인증으로 바꾸거나 HTTP 포트를 쓰세요.

Playwright 프록시 설정, 브라우저·컨텍스트별 IP | Socks5Proxy