پروتکل HTTP و کتابخانه Requests در پایتون
پروتکل HTTP و کتابخانه Requests در پایتون
پروتکل HTTP و کتابخانه Requests در پایتون
.وقتی در مرورگر خود آدرسی را تایپ میکنید یا در پایتون کدی مینویسید که اطلاعاتی را از اینترنت دریافت کند، در حال ورود به دنیای پروتکل HTTP هستید. پروتکل HTTP (مخفف HyperText Transfer Protocol) در واقع «زبان مشترک» و «ستون فقرات» وب است که مشخص میکند چگونه دادهها بین کامپیوترها جابهجا شوند.
فهرست مطالب
کتابخانه requests در پایتون، دقیقاً همان ابزاری است که پیچیدگیهای فنیِ این پروتکل را برای ما پنهان میکند و به ما اجازه میدهد با نوشتن چند خط کد ساده، با دنیای وب سخن بگوییم.
پروتکل HTTP چیست؟ (زبانِ مشترکِ وب)
پروتکل HTTP بر پایه یک مدل تعاملی به نام Client-Server (مشتری-سرور) استوار است. در این مدل، همیشه یک آغازکننده و یک ارائهدهنده وجود دارد:
- Client (مشتری): همان کد پایتون شما یا مرورگر شماست که «درخواست» (Request) میفرستد.
- Server (سرور): کامپیوتری است که اطلاعات را نگه میدارد و به درخواست شما «پاسخ» (Response) میدهد.

نکتهٔ بسیار مهم در درک HTTP این است که این پروتکل Stateless (بدون وضعیت) است. این یعنی سرور هیچ حافظهای از درخواستهای قبلی شما ندارد. هر درخواستِ جدید، کاملاً مستقل از درخواستهای قبلی پردازش میشود. به همین دلیل است که ما برای حفظ «حالتِ کاربر» (مثلاً برای اینکه بدانیم کاربر لاگین کرده است یا نه)، از تکنیکهایی مثل Cookie یا Token در هدرهای درخواست استفاده میکنیم.
کتابخانه requests؛ پلی میان کد و وب
بدون کتابخانه requests، برنامهنویس پایتون مجبور بود درگیر پروتکلهای سطح پایین سوکتنویسی (Socket Programming) شود؛ یعنی مدیریت جزئیاتِ دستوپاگیرِ کانکشنها، هندشیکهای شبکه و فرمتبندیِ بایتها به صورت دستی. کتابخانه requests این پیچیدگی را مدیریت میکند و به شما اجازه میدهد روی «منطقِ برنامهتان» تمرکز کنید. شما فقط آدرس را میدهید و requests تمام بارِ فنیِ برقراریِ ارتباط، ارسالِ درخواست و دریافتِ پاسخ را به دوش میکشد. در ادامه، یاد میگیریم که چطور این تبادلِ اطلاعات را دقیقتر مدیریت کنیم.
ساختار اصلی درخواست و ارتباط HTTP
وقتی به عنوان یک برنامهنویس میخواهید با یک وبسرویس، سرور یا API کار کنید، هر درخواست و تعاملی که شکل میگیرد بر پایه ۴ جزء اصلی در ارسال (Request) و ۱ جزء خروجی در دریافت (Response) بنا شده است:

- آدرس مقصد (URL / Endpoint) : آدرس همان مقصدی است که درخواست را به سمت آن میفرستیم. مشخص میکند دقیقاً با کدام سرور و کدام بخش از برنامه کار داریم.
پروتکل (https://) + دامنه (api.site.com) + مسیر منبع (/v1/users) + پارامترهای جستجو (?id=5).
- ۲. متد (HTTP Method) : قصد و نیت ما از ارسال درخواست را نشان میدهد. رایجترین آنها می توان به
GET،POST،PUT/PATCHوDELETEاشاره کرد. - هدرها (Headers) : شناسنامه، فراداده و دستورالعملهای اضافه است که همراه پیام ارسال میشود (مثل نوع فونت، زبان، مشخصات سیستم و مهمتر از همه کلیدهای امنیتی و نوع فرمت دادهها).
- بدنه (Body / Payload) : بار یا محتوای اصلی که میخواهیم به سرور تحویل دهیم. نکته مهم در درخواستهای خواندنی (
GET) بدنه معمولاً خالی است. اما در درخواستهای ذخیرهسازی و ویرایشی (POST,PUT,PATCH)، دادهها (مثل نام کاربر، رمز، متن یا فایل) در بدنه قرار داده میشوند. - پاسخ سرور (Response) : سرور بعد از دریافت ۴ جزء بالا، پاسخی را آماده کرده و برمیگرداند که شامل اجزای زیر است: کد وضعیت (Status Code)، هدرهای پاسخ (Response Headers) و بدنه پاسخ (Response Body)می باشد.
در کد زیر کاملاً مشخص است که چطور تمام این اجزا به خطوط پایتون نگاشت میشوند:
import requests
# ۱. آدرس مقصد (URL)
url = "https://jsonplaceholder.typicode.com/posts"
# ۲. هدرها (Headers)
headers = {
"User-Agent": "MyPythonApp/1.0",
"Content-Type": "application/json; charset=UTF-8"
}
# ۳. بدنه ارسالی (Body / Payload)
body_data = {
"title": "آموزش جامع Requests",
"body": "در حال یادگیری اجزای ارتباط با وب هستیم.",
"userId": 1
}
# ۴. متد (Method) -> در اینجا requests.post انتخاب شده است
response = requests.post(
url=url,
headers=headers,
json=body_data,
timeout=5
)
# ۵. پردازش پاسخ سرور (Response)
print("=== ساختار پاسخ دریافتی (Response) ===")
print("کد وضعیت (Status Code):", response.status_code)
print("نوع محتوای پاسخ (Header):", response.headers.get("Content-Type"))
print("دادههای برگشتی (Response Body):", response.json())
متدهای اصلی HTTP (چه کارهایی میتوان انجام داد؟)
وقتی با یک سرور یا وبسرویس (API) ارتباط برقرار میکنید، فقط فرستادن آدرس (URL) کافی نیست؛ باید به سرور بگویید دقیقاً چه عملیاتی میخواهید روی آن آدرس انجام دهید.
به این دستورات مشخص در پروتکل HTTP اصطلاحاً HTTP Methods یا HTTP Verbs (افعال HTTP) گفته میشود. کتابخانه requests برای هر یک از این متدها، تابعی کاملاً همنام دارد که کار با آنها را فوقالعاده لذتبخش و ساده میکند.در پروتکل HTTP، برای هر عملیات یک «فعل» یا Method داریم. کتابخانه requests برای هر کدام از این افعال، یک تابع همنام دارد.

برای اینکه در یک نگاه تمام متدهای اصلی، معادل آنها در پایتون و کاربردشان را درک کنید، به جدول زیر توجه کنید:
| تابع در کتابخانه requests | کاربرد اصلی و مفهوم | مثال رایج در برنامهنویسی |
|---|---|---|
| requests.get(url) | خواندن و دریافت اطلاعات از سرور (بدون تغییر دادن دادهها روی سرور) | گرفتن لیست مقالات سایت، دریافت آبوهوا یا اطلاعات پروفایل |
| requests.post(url, json=data) | ارسال و ایجاد دادههای جدید به سرور (دادهها در بدنه یا Body ارسال میشوند) | ثبتنام کاربر، ارسال فرم تماس، فرستادن پرامپت به مدل هوش مصنوعی |
| requests.put(url, json=data) | بهروزرسانی کامل یک منبع (جایگزینی کامل اطلاعات قبلی با دادههای جدید) | ویرایش کامل مشخصات پروفایل کاربری |
| requests.patch(url, json=data) | بهروزرسانی جزئی یک منبع (فقط تغییر دادن یک یا چند فیلد خاص) | تغییر دادن تنها رمز عبور یا ایمیل کاربر |
| requests.delete(url) | حذف کردن یک منبع یا رکورد از روی سرور | پاک کردن یک پست، حذف مدل از اولاما یا حذف حساب کاربری |
الف) متد GET (خواندن و دریافت اطلاعات)
متد GET پرکاربردترین متد وب است. هر بار که صفحهای را در مرورگر باز میکنید، یک درخواست GET ارسال میشود. از این متد فقط برای گرفتن، خواندن و بازیابی دادهها استفاده میشود و هیچ تغییری روی دادههای سرور ایجاد نمیکند (اصطلاحاً Safe است).
import requests
# آدرس منبع: گرفتن مشخصات کاربری با شناسه ۱
url = "https://jsonplaceholder.typicode.com/users/1"
response = requests.get(url)
# بررسی موفقیتآمیز بودن درخواست
if response.status_code == 200:
user_info = response.json()
print(f"نام کاربر: {user_info['name']}")
print(f"ایمیل: {user_info['email']}")
print(f"شهر: {user_info['address']['city']}")
else:
print(f"خطا در دریافت اطلاعات: {response.status_code}")
ب) متد POST (ارسال و ایجاد دادههای جدید)
وقتی میخواهید منبع جدیدی بسازید یا دادهای را برای پردازش به سرور ارسال کنید، از POST استفاده میکنید. کارهایی مثل ثبتنام در سایت، ارسال یک پست جدید به وبلاگ یا فرستادن پرامپت به یک مدل زبانی بزرگ (LLM).
import requests
url = "https://jsonplaceholder.typicode.com/posts"
# دادهای که میخواهیم روی سرور ایجاد شود
new_post_payload = {
"title": "آموزش هوش مصنوعی با پایتون",
"body": "در این مقاله با ساختارهای یادگیری عمیق آشنا میشویم...",
"userId": 1
}
# ارسال داده در قالب JSON
response = requests.post(url, json=new_post_payload)
# در متد POST کد وضعیت موفقیت معمولاً 201 (Created) است
print(f"کد وضعیت: {response.status_code}")
print("پاسخ سرور (رکورد ساختهشده):")
print(response.json())
ج) متد PUT (جایگزینی و بهروزرسانی کامل)
از PUT زمانی استفاده میشود که قصد دارید یک رکورد را بهصورت کامل بازنویسی و جایگزین کنید. یعنی شما تمام فیلدهای منبع را میفرستید؛ اگر فیلدی را نفرستید، سرور معمولاً مقدار آن را خالی یا پیشفرض میگذارد.
import requests
# آدرس پست شماره ۱ که قصد بازنویسی کامل آن را داریم
url = "https://jsonplaceholder.typicode.com/posts/1"
# بسته کامل اطلاعات جدید برای جایگزین شدن
updated_post = {
"id": 1,
"title": "عنوان جدید جایگزینشده",
"body": "متن کامل مقاله که کاملاً با متن قبلی عوض شده است.",
"userId": 1
}
response = requests.put(url, json=updated_post)
print(f"کد وضعیت بهروزرسانی: {response.status_code}")
print("دادههای جدید ثبتشده:")
print(response.json())
د) متد PATCH (بهروزرسانی جزئی و انتخابی)
تفاوت ظریف اما مهم بین PUT و PATCH این است که در PATCH نیازی نیست تمام مشخصات یک رکورد را دوباره ارسال کنید؛ فقط فیلدهایی را میفرستید که میخواهید تغییر کنند (مثلاً فقط تغییر دادن شماره تلفن یا رمز عبور، بدون دستکاری بقیه اطلاعات).
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
# فقط فیلد عنوان (title) را تغییر میدهیم، بقیه فیلدها دستنخورده باقی میمانند
partial_update = {
"title": "عنوان جدید (فقط این فیلد ویرایش شد)"
}
response = requests.patch(url, json=partial_update)
print(f"کد وضعیت: {response.status_code}")
print("خروجی بعد از ویرایش جزئی:")
print(response.json())
ر) متد DELETE (حذف کردن داده)
همانطور که از نامش پیداست، برای حذف دائمی یک رکورد یا فایل از روی سرور به کار میرود (مثلاً حذف یک پیام، پاک کردن حساب کاربری یا حذف فایل آپلود شده).
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
# فقط فیلد عنوان (title) را تغییر میدهیم، بقیه فیلدها دستنخورده باقی میمانند
partial_update = {
"title": "عنوان جدید (فقط این فیلد ویرایش شد)"
}
response = requests.patch(url, json=partial_update)
print(f"کد وضعیت: {response.status_code}")
print("خروجی بعد از ویرایش جزئی:")
print(response.json())
ز) متد HEAD (گرفتن هدرها بدون دانلود محتوا)
دقیقاً شبیه به GET است، با این تفاوت که سرور بدنهی پاسخ (Body) را ارسال نمیکند و فقط هدرها (Headers) را میفرستد. برای چک کردن اینکه آیا یک فایل چند گیگابایتی روی سرور وجود دارد یا اندازه حجم آن چقدر است، بدون اینکه نیاز به دانلود کامل آن باشد!
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.head(url)
print(f"کد وضعیت: {response.status_code}")
print(f"نوع محتوا: {response.headers.get('Content-Type')}")
print(f"حجم تخمینی: {response.headers.get('Content-Length')} بایت")
ژ) متد OPTIONS (پرسیدن دسترسیها و متدهای مجاز)
از سرور میپرسد: «برای این آدرس مشخص، چه متدهایی مجاز هستند؟». کابرد این متد در بررسی سازگاری و تنظیمات امنیتی (بهخصوص مبحث CORS در ارتباطات وب) می باشد.
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.options(url)
# سرور در هدر 'Allow' میگوید چه متدهایی قابل استفاده هستند
print(f"متدهای مجاز برای این مسیر: {response.headers.get('Allow')}")
پاسخ سرور (Response Object)
وقتی سرور به درخواست ما جواب میدهد، کتابخانهٔ requests آن را در یک شیء قدرتمند به نام response بستهبندی میکند. این شیء حاوی تمام اطلاعات حیاتی دربارهٔ سرنوشت درخواست و محتوای بازگشتی است، که شامل اطلاعات حیاتی زیر است:
| ویژگی یا متد | نوع خروجی | کاربرد و توضیح کامل |
|---|---|---|
| response.status_code | عدد صحیح (Integer) | برگرداندن کد وضعیت HTTP (مثل ۲۲۰ برای موفقیت یا ۴۰۴ برای پیدا نشدن) |
| response.json() | دیکشنری یا لیست (dict/list) | تبدیل خودکار دادههای متنی پاسخ (اگر فرمت JSON باشند) به ساختار دادهی پایتون |
| response.text | رشته (String) | نمایش محتوای خام پاسخ سرور به صورت متن یونیکد |
| response.content | بایت (Bytes) | دریافت محتوا به صورت باینری؛ عالی برای دانلود فایل، عکس یا ویدیو |
| response.headers | دیکشنری خاص | نمایش هدرهای (اطلاعات جانبی) پاسخ سرور مثل نوع محتوا یا طول آن |
| response.raise_for_status() | هیچ / یا پرتاب خطا (Exception) | بررسی خودکار خطاهای سرور (4xx و 5xx) و متوقف کردن برنامه در صورت بروز خطا |
| response.url | رشته (String) | نمایش آدرس نهایی (در صورتی که درخواست شما ریدایرکت یا هدایت شده باشد) |
| response.elapsed | زمان (timedelta) | محاسبه و نمایش مدت زمان سپری شده برای دریافت پاسخ از سرور |
۱. کد وضعیت (Status Code)
کد وضعیت یک عدد سهرقمی استاندارد است که مشخص میکند پردازش درخواست به چه سرانجامی رسیده است:
2xx(موفقیت): درخواست با موفقیت دریافت و پردازش شد (مثل200 OK).3xx(تغییر مسیر): برای تکمیل درخواست باید به آدرس دیگری مراجعه کنید (مثل301).4xx(خطای کاربر): اشکال از سمت ارسالکنندهٔ درخواست است (مثل404 Not Found).5xx(خطای سرور): درخواست درست بوده اما سرور در پردازش دچار مشکل شده است (مثل500).
import requests
res = requests.get("https://jsonplaceholder.typicode.com/posts/1")
if res.status_code == 200:
print("درخواست با موفقیت انجام شد!")
elif res.status_code == 404:
print("منبع مورد نظر پیدا نشد.")
۲. هدرها (Headers)
هدرها حکم برچسبهای اطلاعاتی و متادیتا را دارند که سرور همراه پاسخ ارسال میکند؛ اطلاعاتی مثل نوع محتوا (Content-Type) یا زمان پاسخگویی. هدرها در پایتون بهصورت دیکشنریای در دسترس هستند که نسبت به بزرگی و کوچکی حروف حساس نیستند (Case-Insensitive). استفاده از متد .get() مانع از بروز خطای KeyError در صورت نبودن یک هدر خاص میشود.
import requests
res = requests.get("https://jsonplaceholder.typicode.com/posts/1")
# دریافت نوع داده و زمان سرور از هدرها
content_type = res.headers.get("Content-Type")
server_date = res.headers.get("Date")
print(f"نوع محتوا: {content_type}")
print(f"زمان سرور: {server_date}")
۳. متن خام پاسخ (text)
اگر خروجی سرور یک صفحهٔ وب (HTML)، فایل متنی ساده (.txt) یا محتوایی غیر از JSON باشد، از ویژگی text استفاده میکنیم. این ویژگی متن رمزگشاییشدهٔ بدنهٔ پاسخ را بهصورت یک رشته (str) برمیگرداند.
import requests
res = requests.get("https://httpbin.org/robots.txt")
# چاپ محتوای متنی پاسخ
print("محتوای فایل robots.txt:")
print(res.text)
۴. محتوای باینری یا خام (content)
برای دریافت فایلهایی غیر از متن (مانند تصاویر، فایلهای صوتی، ویدیوها یا فایلهای فشرده PDF و ZIP)، استفاده از متن (text) مناسب نیست؛ زیرا ممکن است انکودینگ کاراکترها به فایل آسیب بزند. در این حالت از ویژگی content استفاده میکنیم که دادهها را بهصورت بایت (bytes) خام تحویل میدهد.
import requests
# آدرس یک تصویر نمونه
img_url = "https://httpbin.org/image/png"
res = requests.get(img_url)
if res.status_code == 200:
# ذخیره فایل به صورت باینری (مفید برای عکس، ویدیو و فایل)
with open("downloaded_image.png", "wb") as file:
file.write(res.content)
print("تصویر با موفقیت دانلود و ذخیره شد.")
۵.تبدیل دادههای جیسون (json())
JSON مخفف JavaScript Object Notation یک فرمت سبک، متنی و استاندارد برای ذخیره و انتقال دادههاست. در کار با وب و کتابخانه requests به دلایل زیر با JSON سر و کار داریم.
- زبانمستقل است: فرقی نمیکند سرور با پایتون نوشته شده باشد، java ، php یا nodejs ؛ همه آنها میتوانند دادهها را به فرمت JSON تبدیل کنند و بفرستند.
- شباهت عجیب به پایتون: ساختار JSON دقیقاً شبیه به دیکشنریها (
dict) و لیستها (list) در پایتون است! کلیدها رشته هستند و مقادیر میتوانند متن، عدد، لیست یا حتی دیکشنریهای تو در تو باشند.
یک نمونه متن به فرمت JSON:
{
"username": "mina_ai",
"age": 25,
"skills": ["Python", "Machine Learning", "FastAPI"],
"is_active": true
}
اکثر APIهای مدرن دادهها را به صورت JSON رد و بدل میکنند. وقتی این داده از طریق اینترنت به دست پایتون میرسد، ابتدا یک رشته (String) ساده است. اما کتابخانه requests با متد json() آن را مستقیم به دیکشنری (dict) یا لیست (list) پایتون تبدیل میکند تا بتوانیم مثل کد زیر به راحتی به دادههایش دسترسی داشته باشیم:
import requests
res = requests.get("https://jsonplaceholder.typicode.com/users/1")
# تبدیل خودکار پاسخ JSON به دیکشنری پایتون
user_data = res.json()
print("نام کاربر:", user_data["name"])
print("ایمیل:", user_data["email"])
۶. بررسی خطاهای خودکار (raise_for_status())
بررسی تکتک کدهای وضعیت (404 یا 500) با دستورات if گاهی خستهکننده است. متد raise_for_status() بهصورت خودکار کدهای خطای 4xx و 5xx را تشخیص داده و یک خطای (Exception) استاندارد پرتاب میکند تا برنامهنویس بتواند آن را در بلاک try-except مدیریت کند.
import requests
url = "https://jsonplaceholder.typicode.com/invalid-endpoint"
try:
res = requests.get(url)
# اگر کد وضعیت خطا باشد، این متد استثنا (Exception) ایجاد میکند
res.raise_for_status()
print("پاسخ موفقیتآمیز بود.")
except requests.exceptions.HTTPError as err:
print(f"خطای HTTP رخ داد: {err}")
۷. آدرس نهایی پس از ریدایرکت (url)
گاهی اوقات آدرسی که درخواست را به آن میفرستیم به دلایل امنیتی یا تغییر ساختار، به آدرس دیگری هدایت (Redirect) میشود. ویژگی url نشانی اینترنتی نهایی و واقعی که پاسخ از آن دریافت شده است را به ما نشان میدهد.
import requests
# معمولاً دامنهها بدون www به نسخه دارای www ریدایرکت میشوند
res = requests.get("https://github.com")
print("آدرس اولیه: https://github.com")
print("آدرس نهایی پس از ریدایرکت:", res.url)
۸. زمان پاسخگویی سرور (elapsed)
برای سنجش سرعت سرور یاینکه درخواست ما چقدر معطل مانده است، ویژگی elapsed یک شیء زمانی (timedelta) برمیگرداند که با متد total_seconds() میتوان مدتزمان رفتوبرگشت درخواست را بر حسب ثانیه استخراج کرد.
import requests
# شبیهسازی درخواست با یک ثانیه تاخیر در سرور
res = requests.get("https://httpbin.org/delay/1")
# محاسبه مدت زمان سپری شده
duration = res.elapsed.total_seconds()
print(f"مدت زمان پاسخدهی سرور: {duration:.2f} ثانیه")
مدیریت خطاها
در پروژههای واقعی، همیشه احتمال قطع شدن اینترنت یا در دسترس نبودن سرور وجود دارد. برای اینکه برنامه شما کرش نکند، از دو ابزار مهم استفاده میکنیم: raise_for_status() و try-except.
import requests
try:
# یک آدرس اشتباه عمدی
response = requests.get("https://api.github.com/address-ke-vojod-nadarad")
# اگر کد خطا باشد، اینجا برنامه متوقف شده و میرود داخل except
response.raise_for_status()
print("درخواست موفق بود!")
except requests.exceptions.HTTPError as err:
print(f"خطای HTTP رخ داد: {err}")
except Exception as e:
print(f"یک خطای ناشناخته رخ داد: {e}")
نتیجه گیری
در این مقاله آموختیم که چگونه پروتکل HTTP به عنوان زبان مشترک وب ارتباط میان کلاینت و سرور را شکل میدهد و چگونه کتابخانهٔ قدرتمند requests در پایتون، این فرآیند پیچیده را به چند خط کد ساده تبدیل میکند. با تسلط بر ساختار درخواستها، نحوهٔ ارسال دادهها، و کالبدشکافی شیء پاسخ (Response) شامل کدهای وضعیت، هدرها و بدنههای JSON، اکنون ابزار لازم را در اختیار دارید تا به راحتی به وبسرویسهای مختلف متصل شوید، دادهها را دریافت و پردازش کنید و برنامههای تحت وب خود را هوشمندتر بسازید.
