Skip to main content

Python HTTP Requests

Python HTTP Requests is a core Python concept covering learn how to make HTTP requests in Python using the requests library. Master GET, POST, headers, error handling, and working with REST APIs. This topic is essential for academic learning, board exam preparation, and developing optimized real-world code.

Mentor's Note: The requests library is your passport to the internet. With a few lines of Python, you can talk to any API on the planet. 🌐


The Scenario: The Food Delivery App

Imagine you're building a food delivery app that shows weather-based recommendations.

  • The Need: You need weather data from a remote server — you don't have a weather station on your roof! 📡
  • The Solution: Your app sends an HTTP request to a weather API, and the server sends back a response with the data. This is how all modern apps talk to each other.
  • The Result: Your app shows "Rainy day — 20% off hot soup! ☕" — all powered by a single HTTP request. ✅

What Is the Requests Library?

requests is the de-facto Python library for making HTTP requests. It provides a clean, human-friendly API for calling REST APIs and fetching web resources.

pip install requests

GET Requests

The most common HTTP method — fetch data from a server.

import requests

# Basic GET request
response = requests.get("https://jsonplaceholder.typicode.com/posts/1")

# Status code
print(response.status_code) # 200

# Response body as text
print(response.text) # Raw JSON string

# Response body as Python dict
data = response.json() # Parsed JSON -> dict
print(data["title"]) # Access fields

Response Object Breakdown

import requests

response = requests.get("https://api.github.com")

print(response.status_code) # 200 (success)
print(response.ok) # True (status < 400)
print(response.headers) # Dict of response headers
print(response.elapsed) # Time taken (timedelta)
print(response.encoding) # Character encoding (utf-8)
print(response.url) # Final URL (after redirects)

POST Requests

Send data to a server — create a new resource.

import requests

# Send form-encoded data
payload = {"username": "alice", "email": "[email protected]"}
response = requests.post("https://httpbin.org/post", data=payload)
print(response.json())

# Send JSON data
json_payload = {"title": "Hello", "body": "World", "userId": 1}
response = requests.post(
"https://jsonplaceholder.typicode.com/posts",
json=json_payload
)
print(response.status_code) # 201 (Created)
print(response.json()) # The created resource with ID

Headers and Params

Custom Headers

Many APIs require headers for authentication, content type, or metadata.

import requests

headers = {
"Authorization": "Bearer your_token_here",
"Accept": "application/json",
"User-Agent": "MyApp/1.0"
}

response = requests.get(
"https://api.github.com/user",
headers=headers
)
print(response.json())

Query Parameters

Append parameters to the URL cleanly:

import requests

params = {
"q": "python requests",
"sort": "stars",
"per_page": 5
}

response = requests.get(
"https://api.github.com/search/repositories",
params=params
)

data = response.json()
for repo in data["items"]:
print(f"{repo['full_name']}: {repo['stargazers_count']} ⭐")

Error Handling

Network requests can fail in many ways — always handle exceptions.

import requests
from requests import exceptions

url = "https://api.example.com/data"

try:
response = requests.get(url, timeout=5)

# Raise an error for 4xx/5xx status codes
response.raise_for_status()

data = response.json()
print(data)

except exceptions.Timeout:
print(f"Request to {url} timed out.")

except exceptions.ConnectionError:
print(f"Could not connect to {url}.")

except exceptions.HTTPError as e:
print(f"HTTP error: {e.response.status_code} - {e.response.reason}")

except exceptions.RequestException as e:
print(f"An unexpected error occurred: {e}")

Real Example: Weather API

Fetch current weather from a free API (Open-Meteo — no API key required):

import requests

def get_weather(latitude: float, longitude: float) -> dict:
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": latitude,
"longitude": longitude,
"current_weather": True,
"timezone": "auto"
}

try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Weather fetch failed: {e}")
return {}

# New York City
weather = get_weather(40.7128, -74.0060)

if weather:
current = weather["current_weather"]
temp = current["temperature"]
wind = current["windspeed"]
condition = current["weathercode"]
print(f"NYC: {temp}°C, Wind: {wind} km/h, Code: {condition}")

Authentication: API Keys

Most APIs require authentication via an API key in the headers.

import requests

API_KEY = "your_api_key_here"

headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}

# Option 1: Header-based
response = requests.get(
"https://api.example.com/data",
headers=headers
)

# Option 2: Query parameter-based
response = requests.get(
"https://api.example.com/data",
params={"api_key": API_KEY}
)

# Option 3: Basic auth
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://api.example.com/secure",
auth=HTTPBasicAuth("username", "password")
)

Visual Logic: HTTP Request Flow


Working with JSON APIs

Most modern APIs return JSON. response.json() parses it into Python data structures.

import requests

# Fetch user data
response = requests.get("https://jsonplaceholder.typicode.com/users")
users = response.json() # List of dicts

for user in users:
name = user["name"]
email = user["email"]
city = user["address"]["city"]
print(f"{name:20s} | {email:25s} | {city}")

# POST a new user
new_user = {
"name": "Vishnu",
"email": "[email protected]",
"address": {"city": "Mumbai"}
}

response = requests.post(
"https://jsonplaceholder.typicode.com/users",
json=new_user
)
print(f"Created user with ID: {response.json()['id']}")

Session Objects

For multiple requests to the same server, use a Session — it reuses the TCP connection and persists headers.

import requests

# Create a session with default headers
session = requests.Session()
session.headers.update({
"User-Agent": "MyApp/1.0",
"Accept": "application/json"
})

# All requests share the session
resp1 = session.get("https://api.github.com/users/octocat")
resp2 = session.get("https://api.github.com/users/octocat/repos")

print(resp1.json()["login"])
print(f"Public repos: {len(resp2.json())}")
session.close()

Sample Dry Run

Scenario: Fetch a GitHub user profile

StepCodeResult
1response = requests.get("https://api.github.com/users/octocat")Connection established
2response.status_code200
3response.okTrue
4data = response.json()Python dict with 30+ keys
5data["login"]"octocat"
6data["public_repos"]8
7Error scenario: requests.get("https://bad.url")ConnectionError

Pro Tips

  • Always set a timeout — otherwise your program could hang forever.
  • Use raise_for_status() to catch HTTP errors cleanly.
  • Use Session for performance when making many requests to the same server.
  • response.json() can raise ValueError if the response is not valid JSON — wrap in try/except.

Interview Tip

"Interviewers ask: 'What's the difference between PUT and PATCH?' PUT replaces the entire resource; PATCH applies a partial update. PUT is idempotent — calling it multiple times produces the same result."


← Back: Async/Await | Next: Packaging →

📍 Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
📍 Address
2/66 Faram Street, Rustompura
Surat395002, Gujarat, India
📞 Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition — Areas We Serve in Surat

AdajanAlthanAmroliAthwaAthwalinesBhagalBhatarBhestanCanal RoadChowkCitylightDumasGaurav PathGhod Dod RoadHaziraJahangirpuraKamrejKapodraKatargamLimbayatMagdallaMajura GateMota VarachhaNanpuraNew CitylightOlpadPalPandesaraParle PointPiplodPunaRanderRing RoadRustampuraSachinSalabatpuraSarthanaSosyo CircleUdhnaVarachhaVed RoadVesuVIP Road
📞 Call Sir💬 WhatsApp Sir