빠른 답변
Playwright에서 인증된 프록시는 어떻게 사용하나요?
launch() 또는 new_context()에 server, username, password이 포함된 proxy 객체를 전달하세요: server은 http://gw.crawlrelay.com:7777이고, 자격 증명은 서버 URL에 절대 넣지 않고 별도의 필드에 입력합니다. CrawlRelay 레지덴셜 프록시를 사용할 때는 사용자 이름에 국가와 세션 ID를 넣어 각 컨텍스트마다 고유한 출구를 부여하세요. 트래픽 비용은 50 GB부터 US$0.50/GB이며, KYC 없이 암호화폐로 결제 가능합니다.
Playwright 설정 한눈에 보기
| 프록시 옵션 | {"server": "http://gw.crawlrelay.com:7777", "username": ..., "password": ...} |
|---|---|
| 위치 | 전체 브라우저에 대해 launch(proxy=...), 또는 컨텍스트별로 new_context(proxy=...) |
| 포트 | HTTP 포트 7777; HTTPS 사이트는 CONNECT를 통해 접속 |
| SOCKS5 | Chromium은 SOCKS5 인증을 지원하지 않습니다: HTTP 포트를 사용하세요 |
| 컨텍스트당 하나의 IP | 컨텍스트의 사용자 이름에 -session-<id>-ttl-<minutes> 사용 |
| 일반적인 페이지 트래픽량 | 모든 리소스 포함 약 2 MB; 이미지, 폰트, 미디어 차단 시 수백 KB 수준 |
각 브라우저 컨텍스트에 고유 국가 또는 세션을 어떻게 부여하나요?
국가별 또는 고정 세션별로 하나의 컨텍스트를 만드세요. 컨텍스트는 브라우저보다 비용이 적게 들며, 각 컨텍스트는 쿠키, 저장소, 프록시 자격증명을 독립적으로 유지합니다. 사이트가 일관된 방문자로 인식하도록 컨텍스트 로케일과 출구 국가를 맞추세요.
from playwright.sync_api import sync_playwright
GATEWAY = "http://gw.crawlrelay.com:7777"
LOCALES = {"us": "en-US", "de": "de-DE", "jp": "ja-JP"}
with sync_playwright() as p:
browser = p.chromium.launch()
for country, locale in LOCALES.items():
context = browser.new_context(
proxy={"server": GATEWAY, "username": "USERNAME-country-%s" % country, "password": "PASSWORD"},
locale=locale,
)
page = context.new_page()
page.goto("https://api.ipify.org", wait_until="domcontentloaded")
print(country, page.inner_text("body"))
context.close()
browser.close()Playwright에서 노드.js용 프록시 설정과 트래픽 감소 방법은?
노드.js에서도 옵션 형태는 동일합니다. 렌더된 페이지 중 이미지, 폰트, 미디어가 대부분 용량을 차지하며, HTTP Archive Web Almanac 2025 모바일 기준 중간 페이지 크기는 2,164 KB였습니다. 텍스트와 링크만 필요하다면 라우트 핸들러에서 해당 요청을 중단하세요.
import { chromium } from "playwright";
const browser = await chromium.launch({
proxy: {
server: "http://gw.crawlrelay.com:7777",
username: "USERNAME-country-us-session-pw1-ttl-30",
password: "PASSWORD",
},
});
const context = await browser.newContext();
// Images, fonts and media are most of a page's bytes
await context.route("**/*", (route) =>
["image", "font", "media"].includes(route.request().resourceType()) ? route.abort() : route.continue()
);
const page = await context.newPage();
const response = await page.goto("https://example.com/", { waitUntil: "domcontentloaded" });
console.log(response.status(), await page.title());
await browser.close();asyncio로 여러 페이지를 병렬 실행하려면?
사전에 고정된 컨텍스트 풀을 가진 async API를 사용하세요. 각 컨텍스트는 수명 동안 하나의 고정 세션을 유지하므로 사이트는 각 요청마다 다른 IP가 아닌 몇 명의 안정적인 방문자로 인식합니다. 일정 페이지 수 혹은 오류 발생 후 새 세션 ID로 컨텍스트를 재활용하세요.
import asyncio
import uuid
from playwright.async_api import async_playwright
GATEWAY = "http://gw.crawlrelay.com:7777"
WORKERS = 4
async def worker(browser, queue):
session = uuid.uuid4().hex[:10]
context = await browser.new_context(proxy={
"server": GATEWAY,
"username": "USERNAME-country-us-session-%s-ttl-30" % session,
"password": "PASSWORD",
})
page = await context.new_page()
while not queue.empty():
url = await queue.get()
try:
response = await page.goto(url, wait_until="domcontentloaded", timeout=45000)
print(session, url, response.status if response else None)
except Exception as exc: # timeouts and network errors: log and move on
print(session, url, type(exc).__name__)
finally:
queue.task_done()
await context.close()
async def main(urls):
queue = asyncio.Queue()
for url in urls:
queue.put_nowait(url)
async with async_playwright() as p:
browser = await p.chromium.launch()
await asyncio.gather(*(worker(browser, queue) for _ in range(WORKERS)))
await browser.close()
asyncio.run(main(["https://example.com/", "https://example.org/"]))왜 ERR_TUNNEL_CONNECTION_FAILED 또는 ERR_PROXY_CONNECTION_FAILED가 발생하나요?
- net::ERR_TUNNEL_CONNECTION_FAILED는 프록시가 CONNECT 요청을 수락하지 않았다는 뜻입니다. 대부분 자격 증명이
server안에 작성되어username과password에 제대로 입력되지 않아 Chromium이 전송하지 못한 경우입니다. 터널 오류 참조] - net::ERR_PROXY_CONNECTION_FAILED는 브라우저가 게이트웨이에 도달하지 못했음을 의미합니다: 호스트 또는 포트 오타, 포트를 차단하는 네트워크 문제입니다. 프록시 연결 오류 참조]
goto에서 30000ms 타임아웃 초과는 페이지가 추적기를 계속 로드하여load또는networkidle를 기다리는 경우입니다.domcontentloaded이후 필요한 셀렉터를 기다리세요.
Playwright 스크래퍼가 하지 말아야 할 일은?
JavaScript가 필요한 공개 페이지 렌더링에 Playwright를 사용하고, 사람을 가장하는 데 사용하지 마세요. CrawlRelay의 허용 정책는 대량 계정 생성, 계정 탈취, CAPTCHA 자동 해제나 사이트의 의도적 차단 무력화를 위해 게이트웨이로 브라우저 사용을 금지합니다. 스텔스 플러그인이나 지문 스푸핑은 문서화하지 않습니다. 사이트가 브라우저를 검사하면 속도를 늦추고 robots.txt 및 이용 약관을 확인한 후 접근 허가를 요청하거나 API를 사용하세요.
Playwright와 프록시에 관한 질문
Playwright 컨텍스트마다 다른 프록시를 사용할 수 있나요?
네. 파이썬에서는 proxy을 browser.new_context()에, 노드.js에서는 browser.newContext()에 전달하세요. 각 컨텍스트마다 고유 출구, 쿠키, 저장소가 생깁니다. 윈도우에서 아주 오래된 Playwright 버전은 시작 시 프록시가 필요했는데, 오류가 발생하면 자리 표시자 프록시로 시작 후 실제 프록시를 각 컨텍스트에 설정하세요.
Playwright가 인증 SOCKS5 프록시를 지원하나요?
Chromium은 SOCKS5 사용자 이름과 비밀번호 인증을 지원하지 않습니다. 게이트웨이의 HTTP 포트(7777)를 사용하세요: HTTPS 사이트는 CONNECT 터널로 처리하며 Playwright가 구동하는 모든 브라우저 엔진에서 사용자 이름과 비밀번호를 지원합니다.
Playwright 페이지가 어떤 IP와 국가를 사용하는지 어떻게 확인하나요?
대상 전에 같은 컨텍스트에서 https://api.ipify.org를 열고 본문 텍스트를 읽으세요. 고정 세션이 유지되는 동안만 해당 IP가 유지됨을 유의하세요; 컨텍스트 시작 시 IP를 기록해 변경 여부를 확인하세요.
프록시를 통해 Playwright 페이지가 사용하는 트래픽 양은?
HTML, 스크립트, 스타일, 이미지, 폰트, API 호출 전부 과금 대상입니다. 전체 페이지는 중간값 약 2 MB 정도이며 이미지, 폰트, 미디어 차단 시에도 수백 킬로바이트 수준으로 줄어듭니다. 50개 페이지에 대해 response 핸들러에서 응답 크기 합으로 실제 페이지 크기를 측정하세요.
스크래핑에 헤드리스 브라우저와 헤디드 브라우저 중 어떤 걸 써야 하나요?
헤드리스는 서버에 보통 선택이며 자원이 적게 듭니다. 페이지 표시 내용을 디버깅할 때만 헤디드 브라우저를 사용하세요. 어느 쪽도 규칙을 바꾸지 않으며 공용 페이지를 예의 바르게 렌더링하고 사이트의 robots.txt와 약관을 준수하세요.
레지덴셜 IP를 통해 공용 페이지 렌더링
10 GB용 US$5.94, 50 GB에서 가져온 US$0.50/GB.