수집할 가치가 있는 데이터 중 상당수는 로그인 뒤에 있으며, 이를 스크래핑하는 것은 공개 페이지를 스크래핑하는 것과는 다른 영역입니다. 인증하는 순간 익명 방문자가 아니라 계정을 운영하는 주체가 되며, 계정은 익명 요청과는 전혀 다른 방식으로 속도 제한, 챌린지, 차단을 당합니다. 전체 게임은 “어떤 단일 정체성도 눈에 띄지 않도록 자유롭게 로테이션한다”에서 “계정이 실제이고 일관된 사용자처럼 보이도록 하나의 정체성을 안정적으로 유지한다”로 바뀝니다.
방법을 설명하기 전에 한 가지 유의사항이 있습니다. 접근 권한이 있는 데이터, 즉 본인 소유 계정, 파트너로부터 가져올 권한을 받은 데이터, 사용 권한이 있는 API에서만 스크래핑해야 합니다. 로그인된 데이터는 공개 데이터와는 법적으로나 윤리적으로 다른 범주이며, 스크래핑이 합법인지 여부는 이 경계에 크게 좌우됩니다. 이 가이드는 여러분이 그 경계의 옳은 쪽에 있다고 가정합니다.
공개 스크래핑은 로테이션한다. 인증된 스크래핑은 일관성을 유지한다.
공개 스크래핑에서 얻는 직관은 모든 것을 로테이션하는 것입니다. 요청마다 새로운 IP를 사용하면 어떤 단일 정체성도 눈에 띄지 않게 됩니다. 로그인 뒤에서는 그 직관이 정확히 반대로 작용합니다. 이제는 지속적인 정체성, 즉 계정을 가지고 있으며, 일관성이야말로 그것을 정당하게 보이게 만드는 요소입니다. 한 시간 안에 50개국에서 로그인하거나 세션 도중 IP를 옮겨 다니는 계정은 파워 유저처럼 보이지 않습니다. 탈취된 것처럼 보이며, 그것이 바로 계정 잠금을 유발합니다.
따라서 인증된 스크래핑은 두 가지를 잘하는 것으로 귀결됩니다. 세션을 관리하여 효율적으로 로그인 상태를 유지하는 것, 그리고 각 계정을 안정적이고 깨끗한 정체성에 고정하여 절대 순간이동한 것처럼 보이지 않게 하는 것입니다.
세션 관리
로그인하면 서버는 세션 상태를 반환합니다. 보통은 쿠키이고, 때로는 토큰입니다. 가장 큰 실수는 요청마다 재로그인하는 것입니다. 재인증은 느리고, 로그인이 몰리는 것 자체가 위험 신호입니다. 로그인 엔드포인트는 이를 강하게 속도 제한합니다. 한 번만 로그인하고, 세션을 확보한 뒤, 이를 재사용하세요.
일반 HTTP 클라이언트에서는 쿠키 저장소를 유지하고 프록시를 타는 지속적인 세션 객체를 사용한다는 뜻입니다.
import requests
proxies = {"https": "http://customer-USER-country-us-sid-acct42-ttl-600:PASS@p.shifter.io:443"}s = requests.Session()s.proxies.update(proxies)
# Log in once; the Set-Cookie response populates the jar.s.post("https://example.com/login", data={"user": USER, "password": PW})
# Reuse the same session (and the same sticky IP) for every subsequent request.r = s.get("https://example.com/account/data")그 외에도 중요한 세부사항이 두 가지 있습니다. 많은 사이트는 폼이나 이전 페이지에서 스크래핑하여 쓰기 작업과 함께 전송해야 하는 세션별 CSRF 또는 위조 방지 토큰을 요구하므로, 이를 하드코딩하지 말고 세션에서 읽어오세요. 그리고 많은 사이트는 로그인 후 사이트 자체의 프론트엔드가 호출하는 깔끔한 JSON API를 노출합니다. 네트워크 탭을 살펴보면 종종 이를 발견할 수 있으며, 확보한 쿠키나 토큰으로 이 인증된 API를 직접 호출하는 것이 페이지를 다시 렌더링하는 것보다 훨씬 빠르고 가볍습니다.
각 계정을 하나의 깨끗한 고정 IP에 고정하기
이 지점에서 프록시 계층이 제 역할을 합니다. 계정은 일관된 위치를 보여줘야 하므로, 각 계정은 자신만의 고정 세션을 가져야 합니다. 즉 해당 세션이 지속되는 동안 항상 동일한 레지덴셜 IP를 통해 나가야 하며, 여기서는 사용자 이름의 sid로 인코딩됩니다. 로그인된 계정에서 IP를 로테이션하는 것은 전형적인 차단 유발 요인입니다. 계정이 세션 도중 위치를 옮겨 다니는 것처럼 보이기 때문입니다.
정체성을 유지하게 만드는 요소는 세 가지입니다.
- 지리적 일치. IP는 계정이 평소 운영되는 위치와 일치해야 합니다. 갑자기 독일 IP에 나타나는 미국 계정은 계정 탈취처럼 보이며, 많은 사이트가 재인증 요청이나 잠금으로 응답합니다.
- 깨끗한 평판. 로그인 엔드포인트는 공개 페이지보다 IP 평판을 더 엄격하게 조사합니다. 계정 탈취가 발생하는 지점이기 때문입니다. 플래그가 지정된 주소는 데이터에 도달하기도 전에 2FA 요청, CAPTCHA, “본인 확인” 화면 등 추가적인 마찰을 겪게 됩니다.
- 하나의 계정, 하나의 정체성. 여러 계정을 운영한다면, 각 계정은 공유가 아닌 자신만의 고정 IP를 가져야 합니다. 모두 하나의 주소에서 로그인하는 계정들은 서로 연결되어 함께 플래그가 지정됩니다. 이는 안티디텍트 브라우저가 기기 수준에서 처리하는 이중 계층 정체성의 계정 규모 버전입니다. 별도의 계정, 별도의 IP, 그리고 브라우저를 사용한다면 별도의 핑거프린트가 필요합니다.
다수 계정으로 확장하기
이 패턴은 각 계정을 자신만의 안정적인 정체성에 매핑하고 그 매핑을 유지함으로써 확장됩니다. 레지스트리를 생각해 보세요. 계정에서 고정 sid로, 계정에서 쿠키 저장소로, 그리고 브라우저를 구동한다면 계정에서 브라우저 프로필로 매핑합니다.
# One durable identity per account: same sid -> same exit IP, own cookie jar.def session_for(account): s = requests.Session() sid = f"acct-{account['id']}" s.proxies.update({ "https": f"http://{BASE_USER}-country-{account['geo']}-sid-{sid}-ttl-600:{PW}@p.shifter.io:443" }) load_cookies(s, account) # restore persisted jar, or log in if absent return s그런 다음 하나의 계정에 부하를 강하게 몰아넣기보다는 여러 계정에 부하를 분산시키고, 각 계정과 각 타겟별로 동시성을 제한하세요. 각 계정마다 자체 속도 제한이 있기 때문입니다. 로드 밸런싱 원칙이 적용되지만, 분산 대상이 되는 단위는 단순 IP가 아니라 각각 고정된 정체성을 가진 계정입니다.
실패 모드 처리하기
세 가지 문제가 발생할 수 있으며, 각각에 대한 구체적인 대응이 있습니다.
세션 만료. 세션은 시간이 지나면 만료됩니다. 이를 감지하세요. 로그인 페이지로의 리다이렉트나 401이 그 신호입니다. 그리고 동일한 정체성으로 재인증한 뒤 재개하세요. 핵심 규칙은 재인증할 때 IP를 바꾸지 않는 것입니다. 새로운 위치에서의 재로그인은 만료 자체보다 훨씬 더 의심스럽습니다.
조용한 로그아웃. 때로는 실제로는 로그아웃된 버전의 페이지, 즉 공개 화면은 전부 있지만 계정 데이터는 없는 페이지에 대해 200을 받게 됩니다. 이는 소프트 차단의 인증판 버전입니다. 상태 코드를 신뢰하는 대신 로그인한 사용자만 볼 수 있는 요소가 있는지 확인하여 여전히 로그인 상태인지 검증하세요. 계정 전용 마커가 사라졌다면 빈 행을 기록하기 전에 재인증하세요.
강제 재인증. 2FA 요청이나 “본인 확인” 챌린지는 보통 정체성이 위험하게 보였다는 뜻이며, 흔히 IP가 플래그되었거나 위치가 바뀌었기 때문입니다. 깨끗하고 안정적이며 지리적으로 일치하는 IP가 이런 상황을 드물게 유지시켜줍니다. 그런 일이 발생하면 해당 정체성을 의심 상태로 취급하고 계속 밀어붙이는 대신 물러서세요.
로그인 자체에는 브라우저인가 HTTP인가
도구를 전체 스크래핑이 아니라 로그인 방식에 맞추세요. 쿠키를 반환하는 단순한 폼 로그인은 일반 HTTP 클라이언트로도 충분히 작동합니다. 쿠키를 확보하고, 재사용하며, 가볍게 유지하세요. 하지만 로그인 페이지는 종종 사이트에서 가장 강력하게 방어되는 부분이며, JS 챌린지, SSO 리다이렉트, 동적 토큰, 공격적인 핑거프린팅이 있습니다. 바로 그곳에서 사기가 발생하기 때문입니다. 로그인이 일반 클라이언트에 저항한다면, 실제 브라우저(Playwright, Puppeteer, 또는 Selenium)로 로그인한 뒤, 계속 그것으로 구동하거나 쿠키를 더 가벼운 클라이언트로 내보내 대량 작업을 수행하세요. 이 지점은 TLS 및 HTTP/2 핑거프린팅이 가장 강하게 작용하는 곳이기도 하므로, 나머지 스크래핑이 단순 클라이언트에서 문제없이 작동하더라도 로그인 단계에서는 실제 브라우저의 네트워크 핑거프린트가 종종 차이를 만듭니다.
실행을 신뢰하기 전에 검증하기
인증한 뒤에는 두 가지를 확인하세요. 실제로 로그인되어 있는지(계정 전용 엔드포인트를 가져와서 로그인 마커를 확인), 그리고 예상한 고정 IP를 통해 나가고 있는지(IP 에코 확인은 세션이 지속되는 동안 동일한 주소를 반환해야 합니다). 로그인이 “성공”했지만 계정 마커가 없거나, 요청 사이에 나가는 IP가 흔들리고 있다면, 무엇이든 수집하기 전에 이를 먼저 고치세요. 두 가지 모두 타임아웃 및 탐지 가이드에서 다룹니다.
결론
로그인 뒤에서 스크래핑하는 것은 로테이션이 아니라 정체성 일관성에 관한 것입니다. 계속 재인증하는 대신 한 번 로그인하고 세션을 재사용하고, 각 계정을 하나의 깨끗하고 지리적으로 일치하는 고정 레지덴셜 IP에 고정하고, 하나의 계정에 하나의 정체성을 유지하고, 세션이 만료되면 동일한 정체성으로 재인증하고, 200을 신뢰하는 대신 여전히 로그인 상태인지 검증하세요. 하나의 계정을 여러 주소로 로테이션하는 대신, 각각 자신만의 안정적인 정체성을 가진 계정을 추가함으로써 확장하세요.
이를 제대로 해내면 인증된 수집은 일련의 잠금이 아니라 지속 가능한 것이 됩니다. 계정당 깨끗하고 고정된 레지덴셜 IP가 전체의 기반이 되며, GB당 가격 정책 덕분에 많은 안정적인 계정 정체성을 운영하면서도 각 계정이 실제로 가져온 데이터에 대해서만 비용을 지불할 수 있습니다.