본문 바로가기
카테고리 없음

파이썬 크롤링 아이디 비밀번호 맞는데 로그인 안 될 때

by heeday4753 2026. 3. 29.

로그인 크롤링을 할 때 아이디와 비밀번호를 정확히 넣었는데도 계속 로그인에 실패하는 경우가 있습니다. 계정 정보가 잘못된 줄 알았는데, 알고 보니 화면에 안 보이는 숨겨진 값이 빠져 있었습니다. 이번 글에서는 로그인 폼 분석이 왜 중요한지, 토큰 누락 문제를 어떻게 확인하고 해결했는지 정리했습니다.

 

 

아이디와 비밀번호만 보내면 로그인되지 않는 이유

 

처음 로그인 크롤링을 할 때 가장 많이 하는 생각은 단순합니다. 로그인 화면에 아이디 입력칸과 비밀번호 입력칸이 있으니, 코드에서도 그 두 값만 보내면 끝날 것 같다는 판단입니다. 실제로 저도 requests.post()에 아이디와 비밀번호를 넣고 실행해봤는데, 응답 코드는 정상처럼 보였지만 로그인은 되지 않았습니다. 회원 페이지로 이동하면 다시 로그인 화면이 나왔고, 어떤 경우에는 오류 메시지도 없이 그냥 실패했습니다.

 

이 문제는 사이트가 로그인 검증에 아이디와 비밀번호만 쓰지 않기 때문에 생깁니다. 많은 사이트는 보안상 이유로 숨겨진 입력값을 함께 전송하게 만듭니다. 대표적으로 csrf_token, authenticity_token, returnUrl, state 같은 값이 있습니다. 사용자는 화면에서 이 값을 직접 보지 못하지만, 브라우저는 로그인 버튼을 누를 때 이 값까지 함께 서버에 보냅니다. 화면만 보고 폼을 흉내 내면 이 값이 빠진 채 요청이 나가는 겁니다.

 

이럴 때 흔히 보이는 증상은 몇 가지로 정리됩니다. 첫째, 응답 코드는 200인데 실제 로그인은 되지 않습니다. 둘째, 로그인 실패 메시지가 HTML 안에는 있는데 화면으로는 잘 드러나지 않습니다. 셋째, 로그인 성공 후 가야 할 페이지가 아니라 다시 로그인 페이지로 돌아갑니다. 넷째, 사이트에 따라서는 아예 비정상 요청으로 판단하고 차단하기도 합니다. 보이는 입력값만 보내는 게 아니라, 브라우저가 실제로 뭘 같이 보내는지 먼저 봐야 합니다.

초보자일수록 여기서 막히기 쉽습니다. 로그인은 단순한 한 번의 POST 요청처럼 보여도, 실제로는 로그인 페이지 접속 → 숨겨진 토큰 수신 → 로그인 요청 전송 → 서버 검증 → 세션 발급이라는 흐름으로 움직이는 경우가 많기 때문입니다. 그래서 코드 짜기 전에 폼 구조를 읽는 게 먼저입니다.

파이썬 크롤링 아이디 비밀번호 맞는데 로그인 안 될 때

 

 

로그인 폼을 분석하고 토큰을 함께 보내면 해결됩니다

 

해결 방법은 생각보다 명확합니다. 로그인 요청을 보내기 전에 먼저 로그인 페이지를 한 번 가져오고, 그 안에 포함된 숨겨진 값을 추출한 뒤, 아이디와 비밀번호와 함께 다시 전송하면 됩니다. requests.Session()을 같이 쓰면 이후 흐름까지 끊기지 않습니다. 토큰과 세션을같이 챙기는 게 로그인 크롤링의 기본입니다.

아래는 가장 기본적인 예시입니다.

import requests
from bs4 import BeautifulSoup

login_page_url = "https://example.com/login"
login_action_url = "https://example.com/login/check"

with requests.Session() as session:
    # 1. 로그인 페이지 먼저 요청
    page_response = session.get(login_page_url)
    soup = BeautifulSoup(page_response.text, "html.parser")

    # 2. hidden input에서 토큰 추출
    csrf_token = soup.find("input", {"name": "csrf_token"})["value"]

    # 3. 로그인에 필요한 데이터 구성
    payload = {
        "user_id": "내아이디",
        "password": "내비밀번호",
        "csrf_token": csrf_token
    }

    # 4. 로그인 요청 전송
    login_response = session.post(login_action_url, data=payload)

    print("로그인 응답 코드:", login_response.status_code)
    print("현재 URL:", login_response.url)
    print("현재 쿠키:", session.cookies.get_dict())

 

이 코드에서 중요한 부분은 두 가지입니다. 첫 번째는 로그인 페이지를 먼저 요청해서 숨겨진 값을 추출한다는 점입니다. 두 번째는 그 값을 같은 세션 안에서 다시 로그인 요청에 포함한다는 점입니다. csrf_token이라는 이름은 예시일 뿐입니다. 사이트마다 다르니 개발자 도구에서 직접 확인해야 합니다.

 

또 하나 자주 놓치는 부분은 input 태그의 name입니다. 화면에 "아이디"라고 적혀 있어도 실제 전송 파라미터는 username, userId, login_id처럼 다를 수 있습니다. HTML 소스에서 name 속성을 직접 확인하지 않으면 계속 같은 자리에서 막힙니다. 그리고 어떤 사이트는 토큰 값이 매 요청마다 바뀌므로, 예전에 복사한 값을 하드코딩해서 쓰면 다시 실패합니다. 매번 로그인 페이지에서 새 값을 받아와야 합니다.

 

실제로 작업할 때는 다음 순서로 점검하면 훨씬 수월합니다. 먼저 브라우저 개발자 도구를 열고 로그인 요청을 확인합니다. 그다음 Form Data에 어떤 값이 들어가는지 봅니다. 그중 눈에 익지 않은 hidden 값이 있는지 확인합니다. 이후 코드에서 로그인 페이지를 먼저 요청하고, 해당 값을 추출해 함께 전송합니다. 이 순서만 지켜도 단순 로그인 실패는 대부분 해결됩니다.

 

 

로그인 크롤링은 화면이 아니라 실제 전송값을 따라가야 합니다

 

로그인 크롤링은 보이는 화면을 따라 하는 작업이 아닙니다. 브라우저가 실제로 전송하는 데이터를 따라가는 작업입니다. 아이디와 비밀번호만 맞으면 될 것 같았지만, 숨겨진 토큰까지 맞춰야 서버가 정상 요청으로 받아들입니다.

이걸 한 번 이해해두면 다른 사이트를 크롤링할 때도 같은 방식으로 접근할 수 있습니다. 사이트마다 화면 구성은 달라도 로그인 구조의 핵심은 비슷하기 때문입니다. 로그인 페이지를 먼저 불러오고, hidden input을 확인하고, 실제 전송 파라미터를 맞추는 것. 이 흐름이 익숙해지면 시행착오가 확실히 줄어듭니다. 응답 코드만 보고 성공 여부를 판단하는 습관은 버리는 게 좋습니다. 로그인 후 최종 URL, 쿠키 생성 여부, 회원 페이지 접근 가능 여부까지 같이 확인해야 진짜 성공인지 알 수 있습니다.

로그인이 막힐 때 비밀번호부터 다시 확인하기 전에, 폼 데이터를 먼저 의심해보는 것만으로도 시간을 많이 아낄 수 있습니다.

 

 

 


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 블로그 이름