🌐 HTTP Requests: Your Python Messenger to the Internet
The Story: Meet Your Digital Postman
Imagine you want to send a letter to a friend across the world. You write your message, put it in an envelope, hand it to the postman, and wait for a reply. HTTP requests in Python work exactly the same way!
Your Python program is YOU. The internet is the world. And the requests library? That’s your super-fast digital postman who can deliver messages anywhere in milliseconds!
📬 Making GET Requests: “Hey, Can I See That?”
What is a GET Request?
Think of GET like walking up to a library and saying:
“Can I see the book about dinosaurs?”
You’re asking to look at something. You don’t change anything. You just want to read.
Simple Example
import requests
# Ask Google for their homepage
response = requests.get("https://www.google.com")
# Did we get it?
print(response.status_code) # 200 means "Here you go!"
Real-World Example: Getting Weather
import requests
# Ask for weather data
url = "https://api.weather.com/today"
response = requests.get(url)
# Read what we got back
weather = response.json()
print(f"Today: {weather['temp']}°")
What Makes GET Special?
| Feature | GET Request |
|---|---|
| Purpose | Read data |
| Changes data? | Never |
| Safe to repeat? | Yes! |
📮 Making POST Requests: “Here’s Something New!”
What is a POST Request?
POST is like mailing a package to someone:
“Hey, I’m sending you something new!”
You’re creating or submitting new data.
Simple Example: Sending a Message
import requests
url = "https://api.example.com/messages"
# The message we want to send
my_message = {
"to": "friend@email.com",
"text": "Hello from Python!"
}
# Send it!
response = requests.post(url, json=my_message)
print(response.status_code) # 201 = "Created!"
The Difference: GET vs POST
graph TD A["You want data?"] --> B{What kind?} B --> |Read existing| C["Use GET"] B --> |Send new data| D["Use POST"] C --> E["Library: Show me a book"] D --> F["Library: Add my new book"]
Quick Comparison
| Action | Method | Example |
|---|---|---|
| Read profile | GET | requests.get(url) |
| Create account | POST | requests.post(url, data) |
| View photo | GET | requests.get(photo_url) |
| Upload photo | POST | requests.post(url, files) |
📋 Request Headers: Your ID Badge
What Are Headers?
Imagine entering a building with special rooms. The security guard needs to know:
- Who are you?
- What language do you speak?
- What type of visitor are you?
Headers are your ID badge that tell the server about you!
Common Headers You’ll Use
import requests
url = "https://api.example.com/data"
# Your "ID badge" information
headers = {
"Authorization": "Bearer my-secret-key",
"Content-Type": "application/json",
"User-Agent": "MyPythonApp/1.0"
}
response = requests.get(url, headers=headers)
What Each Header Means
| Header | Purpose | Analogy |
|---|---|---|
Authorization |
Proves who you are | Your password/key |
Content-Type |
What format is data | “I speak JSON” |
User-Agent |
Identifies your app | Your name tag |
Accept |
What you can read | “I understand JSON” |
Example: API with Authentication
import requests
api_key = "your-secret-key"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "application/json"
}
response = requests.get(
"https://api.github.com/user",
headers=headers
)
print(response.json()["name"])
📨 Response Handling: Reading Your Mail
What Do You Get Back?
When your postman returns, they bring back:
- A status code - Did it work?
- Headers - Extra info about the reply
- Body - The actual content/data
Status Codes: The Quick Answer
import requests
response = requests.get("https://api.example.com")
# Check the status
if response.status_code == 200:
print("Success! Here's your data.")
elif response.status_code == 404:
print("Oops! Page not found.")
elif response.status_code == 500:
print("Server had a problem.")
Understanding Status Codes
| Code | Meaning | Emoji |
|---|---|---|
| 200 | OK! Success! | ✅ |
| 201 | Created new thing | 🆕 |
| 400 | Bad request (your mistake) | ❌ |
| 401 | Not authorized | 🔐 |
| 404 | Not found | 🔍 |
| 500 | Server error | 💥 |
Reading the Response Body
import requests
response = requests.get("https://api.example.com/user")
# As plain text
text_data = response.text
print(text_data)
# As JSON (most APIs use this)
json_data = response.json()
print(json_data["name"])
# Response headers
print(response.headers["Content-Type"])
graph TD A["Send Request"] --> B["Get Response"] B --> C{Check Status} C --> |200-299| D["Read Body"] C --> |400-499| E["Fix Your Request"] C --> |500-599| F["Server Problem"] D --> G["Use the Data!"]
🔄 Session Objects: Your VIP Pass
The Problem Without Sessions
Imagine going to a theme park. Every single ride, you show your ticket. Get on, show ticket. Next ride, show ticket. Exhausting!
What if you had a wristband that proved you paid? Show it once, ride all day!
Sessions = Your Wristband
import requests
# Create your VIP wristband
session = requests.Session()
# Set it up once
session.headers.update({
"Authorization": "Bearer my-token",
"User-Agent": "MyApp/1.0"
})
# Now ALL requests use these automatically!
response1 = session.get("https://api.example.com/profile")
response2 = session.get("https://api.example.com/settings")
response3 = session.post("https://api.example.com/update")
# No need to add headers each time!
Why Use Sessions?
| Without Session | With Session |
|---|---|
| Add headers every request | Set headers once |
| Manage cookies manually | Cookies handled for you |
| Each request is separate | Requests share connection |
| Slower | Faster! |
Session with Cookies (Login Example)
import requests
session = requests.Session()
# Login once
login_data = {
"username": "me",
"password": "secret"
}
session.post("https://site.com/login", data=login_data)
# Now you're logged in for ALL requests!
profile = session.get("https://site.com/my-profile")
orders = session.get("https://site.com/my-orders")
# Both work because session remembers you!
🛡️ Error Handling: When Things Go Wrong
Why Errors Happen
The internet isn’t perfect. Things go wrong:
- Website is down
- Your internet disconnected
- Request took too long
- Server rejected you
Good code handles these gracefully!
The Try-Except Pattern
import requests
try:
response = requests.get(
"https://api.example.com/data",
timeout=5 # Wait max 5 seconds
)
response.raise_for_status() # Raise error if bad status
data = response.json()
print(data)
except requests.exceptions.Timeout:
print("Request took too long!")
except requests.exceptions.ConnectionError:
print("Can't connect to internet!")
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"Something went wrong: {e}")
Common Errors You’ll See
graph TD A["Make Request"] --> B{Error?} B --> |No| C["Success!"] B --> |Timeout| D["Took too long"] B --> |ConnectionError| E["No internet"] B --> |HTTPError| F["Bad status code"] B --> |JSONDecodeError| G["Bad response format"]
Error Types Explained
| Error | What Happened | How to Fix |
|---|---|---|
Timeout |
Server too slow | Increase timeout or retry |
ConnectionError |
No internet | Check connection |
HTTPError |
400/500 status | Check URL and data |
JSONDecodeError |
Bad JSON | Check response format |
The Safe Request Pattern
import requests
def safe_request(url):
"""Make a request that won't crash your program"""
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
return None
# Use it safely
data = safe_request("https://api.example.com")
if data:
print("Got data!", data)
else:
print("Couldn't get data, try again later")
🎯 Putting It All Together
Here’s a complete example using everything you learned:
import requests
class APIClient:
"""A proper API client with all best practices"""
def __init__(self, base_url, api_key):
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
})
self.base_url = base_url
def get(self, endpoint):
"""Safe GET request"""
try:
url = f"{self.base_url}{endpoint}"
response = self.session.get(url, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"GET failed: {e}")
return None
def post(self, endpoint, data):
"""Safe POST request"""
try:
url = f"{self.base_url}{endpoint}"
response = self.session.post(
url, json=data, timeout=10
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"POST failed: {e}")
return None
# Use it!
api = APIClient("https://api.mysite.com", "my-key")
user = api.get("/users/me")
new_post = api.post("/posts", {"title": "Hello!"})
🌟 You Did It!
You now understand:
- ✅ GET requests - Ask to see data
- ✅ POST requests - Send new data
- ✅ Headers - Your ID badge to the server
- ✅ Response handling - Read what comes back
- ✅ Sessions - Your VIP pass for multiple requests
- ✅ Error handling - Gracefully handle problems
You’re now ready to connect your Python programs to any API on the internet! 🚀
💡 Pro Tip: Always use
timeoutin your requests. Without it, your program could wait forever if a server doesn’t respond!
