로컬 API로 브라우저 프로필 자동화하기

스크립트에서 프로필을 시작하고 디버깅 엔드포인트를 받아, 신원과 프록시가 이미 적용된 브라우저에 Playwright나 Puppeteer를 연결하세요.
안티디텍트 브라우저 자동화는 흔히 어려운 문제처럼 소개됩니다. 하지만 도구가 자동화 라이브러리가 이미 사용할 줄 아는 단 한 가지, 즉 디버깅 엔드포인트를 건네주기만 한다면 어렵지 않습니다.
전체 구조
PowerOps는 루프백 주소에 바인딩된 HTTP API를 실행합니다. 스크립트가 프로필을 시작하라고 요청하면, 해당 프로필의 신원, 스토리지, 프록시가 이미 적용된 상태로 브라우저를 실행하고 실행 중인 브라우저의 WebSocket 엔드포인트를 반환합니다. 스크립트는 Playwright, Puppeteer 또는 DevTools 프로토콜을 사용하는 다른 어떤 도구로든 그 엔드포인트에 연결합니다.
자동화 라이브러리는 핑거프린트가 무엇인지 알 필요가 전혀 없습니다. 연결되는 시점에는 환경이 이미 갖춰져 있기 때문입니다.
프로필 시작하기
curl -s -H "Authorization: Bearer $POWEROPS_API_KEY" \
http://127.0.0.1:50326/status
상태 확인을 제외한 모든 라우트에는 Bearer 키가 필요합니다. 브라우저를 시작하면 연결할 엔드포인트가 반환됩니다.
curl -s -X POST \
-H "Authorization: Bearer $POWEROPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"profileId": "..."}' \
http://127.0.0.1:50326/browser/start
라이브러리 연결하기
import { chromium } from "playwright";
const res = await fetch("http://127.0.0.1:50326/browser/start", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.POWEROPS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ profileId }),
});
const { ws } = await res.json();
// The profile's identity, storage and proxy are already in place.
const browser = await chromium.connectOverCDP(ws);
const [context] = browser.contexts();
const page = context.pages()[0] ?? await context.newPage();
await page.goto("https://example.com");
중요한 것은 주석 줄입니다. 스크립트에는 핑거프린트 설정이 전혀 없습니다. 환경을 구성하는 일은 스크립트의 일이 아니기 때문입니다. 그것은 프로필에 속하며, 사람이 행을 클릭해서 열든 새벽 3시에 예약된 작업이 열든 똑같이 유지됩니다.
API가 다루는 범위
- 상태 라우트는 헬스 체크이며, 키가 필요 없는 유일한 라우트입니다.
- 브라우저 라우트는 현재 실행 중인 브라우저를 시작, 중지, 조회합니다.
- 프로필 라우트는 프로필을 생성, 수정, 조회, 삭제합니다.
- 프록시 라우트는 프록시 라이브러리를 관리하고 경로를 할당합니다.
- 그룹 라우트는 프로필을 일괄 정리합니다.
- 확장 프로그램 라우트는 확장 프로그램을 가져오고 할당합니다.
로컬로 유지되는 방식
로그인된 계정이 들어 있는 브라우저를 구동하는 API라면 그 경계에 대해 한마디 할 만합니다.
- 127.0.0.1에 바인딩됩니다. 다른 인터페이스에서 수신하도록 만드는 설정은 없습니다.
- 상태 확인을 제외한 모든 라우트에 Bearer 키가 필요합니다.
- Host 헤더를 검증하고 CORS 헤더를 보내지 않으므로, 평소 사용하는 브라우저에 열려 있는 웹 페이지가 접근할 수 없습니다.
- 비밀 값은 쓰기 전용입니다. 프로필 비밀번호, 2단계 인증 비밀 값, 프록시 비밀번호는 조회 라우트에서 절대 반환되지 않습니다.
따라 해 볼 만한 패턴
그룹의 프로필을 조회하고, 하나씩 시작하고, 작업을 하고, 중지합니다. 한꺼번에 모두 실행하지 말고 몇 개씩 나누어 실행하세요. 제약은 내 컴퓨터의 메모리입니다. 각 프로필이 실제 브라우저 프로세스이기 때문입니다.
const { profiles } = await api("/profiles?groupId=" + groupId);
for (const batch of chunk(profiles, 5)) {
await Promise.all(batch.map(async (profile) => {
const { ws } = await api("/browser/start", { profileId: profile.id });
try {
await doTheWork(ws);
} finally {
await api("/browser/stop", { profileId: profile.id });
}
}));
}
`finally`에서 프로필을 중지하는 것은 보이는 것보다 훨씬 중요합니다. 깨끗하게 닫아야 브라우저 상태가 기록되며, 세션 도중에 강제 종료된 프로필은 방금 확립한 세션을 잃을 수 있습니다.
