Lỗi 403, 429, 503 khi scrape — nguyên nhân và cách xử lý đúng (có code Python)
Trong bài này
Khi scraper bắt đầu nhận lỗi, phản xạ phổ biến nhất là "đổi IP". Nhưng mỗi mã lỗi HTTP nói một điều khác nhau, và đổi IP chỉ đúng với một số ít trường hợp. Đọc đúng mã lỗi giúp bạn sửa đúng chỗ — và tránh biến một giới hạn tạm thời thành một lệnh chặn lâu dài. Bài này đi qua các lỗi hay gặp nhất khi scrape qua proxy, kèm code Python xử lý chuẩn.
Đọc mã lỗi trước khi đổi IP
| Mã | Ý nghĩa | Nên làm gì |
|---|---|---|
| 429 | Quá nhiều request | Chờ theo Retry-After, giảm tốc |
| 403 | Bị từ chối | Tìm nguyên nhân; không thử lại mù quáng |
| 503 | Quá tải hoặc trang thử thách | Lùi lại; đọc nội dung trả về |
| 401 | Trang cần đăng nhập | Dữ liệu không công khai — xem lại |
| 407 | Proxy từ chối tài khoản | Sửa tài khoản, mật khẩu proxy |
| 404 | Không có trang | Sửa URL; đừng thử lại |
| Lỗi kết nối, timeout | Mạng hoặc proxy đang kết nối lại | Thử lại sau vài giây |
Phân biệt quan trọng: 407 đến từ proxy, còn 401, 403, 429, 503 đến từ trang web. Lỗi phía proxy có trong bài các lỗi proxy thường gặp.
429 Too Many Requests
Trang đang nói rõ: bạn gửi quá nhiều request trong một khoảng thời gian. Đây là lỗi "lịch sự" nhất — trang chưa chặn, chỉ yêu cầu bạn chậm lại.
- Đọc header
Retry-After. Nó cho biết phải chờ bao lâu: một số giây (Retry-After: 120) hoặc một mốc thời gian. - Không có header thì lùi dần — chờ 5, 10, 20, 40 giây… kèm một chút ngẫu nhiên.
- Giảm tốc độ chung sau khi gặp 429, không chỉ cho request bị lỗi.
Đổi IP để né 429 chỉ dời vấn đề: tốc độ của bạn vẫn vậy, và bạn sẽ gặp lại 429 trên IP mới — đôi khi kèm một lệnh chặn nặng hơn.
403 Forbidden
Trang hiểu request nhưng từ chối phục vụ. Nguyên nhân phổ biến:
- IP thuộc dải máy chủ và trang chặn cả dải — thử cùng URL qua proxy 4G.
- Chương trình không giống trình duyệt — thiếu
User-Agent,Accept,Accept-Language. - Nội dung bị giới hạn theo quốc gia — IP sai nước.
- Trang cấm truy cập tự động vào phần đó.
Cách chẩn đoán nhanh: mở đúng URL đó bằng trình duyệt bình thường qua cùng proxy. Trình duyệt vào được mà script không vào được → vấn đề ở script. Trình duyệt cũng bị 403 → vấn đề ở IP hoặc quốc gia. Nếu trang chặn rõ ràng việc truy cập tự động, hãy dừng lại — xem scrape website có chống bot.
503 và trang thử thách
503 có hai nghĩa rất khác nhau:
- Trang quá tải hoặc đang bảo trì — thường kèm
Retry-After. Lùi lại, và cân nhắc giảm tốc vì có thể chính bạn góp phần gây quá tải. - Trang thử thách của dịch vụ chống bot — nội dung trả về là trang "đang kiểm tra trình duyệt" chứ không phải dữ liệu.
Hãy ghi lại một phần nội dung của phản hồi lỗi để phân biệt hai trường hợp. Gặp thử thách liên tục nghĩa là trang không muốn lưu lượng tự động; thử lại nhanh hơn chỉ làm mọi thứ tệ hơn.
401 và 407
- 401 Unauthorized — trang cần đăng nhập. Dữ liệu này không công khai; lấy nó tự động thường vi phạm điều khoản.
- 407 Proxy Authentication Required — proxy không nhận tài khoản, mật khẩu của bạn. Kiểm tra lại thông tin proxy, và mã hoá ký tự đặc biệt trong mật khẩu. Chi tiết trong bài lỗi 407.
Lỗi kết nối và timeout
Với proxy 4G, lỗi kết nối ngắn là bình thường ngay sau khi đổi IP: thiết bị cần vài giây để kết nối lại mạng di động. Một vài lỗi lúc sóng yếu cũng có thể xảy ra.
- Đặt timeout hợp lý (20–30 giây) thay vì chờ vô hạn.
- Thử lại sau vài giây với lỗi kết nối, có giới hạn số lần.
- Sau khi đổi IP, chờ tới khi proxy chạy lại trước khi gửi request — code mẫu có trong bài đổi IP proxy bằng API.
Khi nào đổi IP là hợp lý
- IP hiện tại bị gắn cờ vì người khác. IP di động dùng chung với nhiều thuê bao, nên đôi khi bị giới hạn trước cả khi bạn bắt đầu.
- Bắt đầu một phiên mới — một đợt chạy mới, một hồ sơ mới.
- Kết nối từ thiết bị chập chờn kéo dài.
Đổi IP không phải cách xử lý 429 do bạn đi quá nhanh, hay 403 do trang cấm truy cập tự động. Với 65Proxy, mỗi proxy đổi IP tối đa một lần mỗi 5 phút — một giới hạn vô tình rất hợp với cách dùng đúng.
Code mẫu: xử lý lỗi đúng cách
Đoạn Python dưới đây chờ theo Retry-After khi gặp 429 hoặc 503, lùi dần khi lỗi kết nối, và không thử lại mù quáng với 403 hay 404. Cài bằng pip install requests và đặt biến môi trường PROXY:
import os
import random
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
import requests
PROXY = os.environ["PROXY"] # http://USER:PASS@HOST:PORT
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = "my-crawler/1.0 (+mailto:[email protected])"
def retry_after(resp):
"""Số giây cần chờ theo header Retry-After, hoặc None."""
value = resp.headers.get("Retry-After", "").strip()
if value.isdigit():
return int(value)
try:
when = parsedate_to_datetime(value)
except (TypeError, ValueError):
return None
if when.tzinfo is None:
when = when.replace(tzinfo=timezone.utc)
return max(0, (when - datetime.now(timezone.utc)).total_seconds())
def fetch(url, max_tries=5):
delay = 5
for _ in range(max_tries):
try:
resp = session.get(url, timeout=30)
except requests.RequestException as err:
print(f"lỗi kết nối: {err}")
else:
if resp.status_code < 400:
return resp
if resp.status_code not in (429, 503):
resp.raise_for_status() # 403, 404…: dừng, đừng thử lại
wait = retry_after(resp)
if wait is not None:
print(f"{resp.status_code}: chờ {wait:.0f} giây theo Retry-After")
time.sleep(wait)
continue
time.sleep(delay + random.uniform(0, delay / 2))
delay = min(delay * 2, 300)
raise RuntimeError(f"bỏ qua {url} sau {max_tries} lần thử")
for url in ["https://example.com/page/1", "https://example.com/page/2"]:
print(url, fetch(url).status_code)
time.sleep(random.uniform(3, 6)) # nghỉ giữa các trangNếu 429 vẫn xuất hiện thường xuyên, đừng tăng số lần thử — hãy tăng thời gian nghỉ giữa các trang.
Câu hỏi thường gặp
Gặp 429 thì đổi IP luôn có được không?
Được về kỹ thuật, nhưng không nên. 429 nghĩa là bạn đi quá nhanh; IP mới với cùng tốc độ sẽ gặp lại 429, và việc liên tục đổi IP để né giới hạn là hành vi các trang nhận ra rất nhanh.
Vì sao trình duyệt vào được mà script bị 403?
Vì trang nhận ra script không phải trình duyệt — qua header thiếu, dấu vân tay TLS hoặc vì không chạy JavaScript. Xem website phát hiện proxy bằng cách nào.
Nên thử lại bao nhiêu lần?
Ba tới năm lần cho lỗi tạm thời (429, 503, lỗi kết nối), với thời gian chờ tăng dần. Không thử lại với 403, 404 và 401 — chúng sẽ không tự hết.