Ojasa Mirai

Ojasa Mirai

Python

Loading...

Learning Level

🟢 Beginner🔵 Advanced
REST API BasicsHTTP RequestsStatus CodesJSON SerializationError HandlingAPI AuthenticationRate LimitingBuilding APIsWeb Scraping Basics
Python/Apis Json/Http Requests

📨 HTTP Requests — Mastering Client-Server Communication

HTTP requests are the fundamental mechanism for sending data to and receiving data from web servers. Whether you're fetching data from an API, submitting a form, or downloading a file, you're making HTTP requests. Mastering this skill opens doors to countless web development possibilities.


🎯 What is an HTTP Request?

An HTTP request is a message sent from a client (like your Python script) to a server asking it to perform an action or provide information. Every request follows a standardized format with a method, URL, headers, and optional body.

import requests

# Simple HTTP request
response = requests.get('https://api.github.com/users/octocat')
print(response.status_code)  # 200 = success
print(response.text)         # Response body as string

🔧 The Requests Library

The `requests` library makes working with HTTP super simple. It handles all the complexity of HTTP protocols behind the scenes.

import requests

# Installation: pip install requests

# Basic structure of a request
response = requests.get(url)
# response contains:
# - status_code: HTTP status (200, 404, 500, etc.)
# - headers: Dictionary of response headers
# - text: Response body as string
# - json(): Parse response body as JSON
# - content: Response body as bytes

🌐 Making GET Requests

GET requests retrieve data from a server without changing anything. They're the most common type of request.

Simple GET Request

import requests

# Get data from an API
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')

# Check if request was successful
if response.status_code == 200:
    data = response.json()
    print(f"Title: {data['title']}")
else:
    print(f"Error: {response.status_code}")

GET with Query Parameters

Query parameters filter or customize the data returned:

import requests

# Method 1: Add parameters to URL string
response = requests.get('https://jsonplaceholder.typicode.com/posts?userId=1&_limit=5')

# Method 2: Use params dictionary (cleaner)
params = {
    'userId': 1,
    '_limit': 5,
    '_sort': 'id',
    '_order': 'desc'
}
response = requests.get('https://jsonplaceholder.typicode.com/posts', params=params)
print(response.url)  # See the actual URL with parameters

📤 Making POST Requests

POST requests create new resources on the server. You send data in the request body.

POST with JSON Data

import requests

# Data to send
new_post = {
    'title': 'My First API Post',
    'body': 'This is created via Python!',
    'userId': 1
}

# Send POST request
response = requests.post(
    'https://jsonplaceholder.typicode.com/posts',
    json=new_post  # Automatically converts dict to JSON
)

# Check response
print(f"Status: {response.status_code}")
created_post = response.json()
print(f"Created post ID: {created_post['id']}")

POST with Form Data

import requests

# Form data (like submitting an HTML form)
form_data = {
    'username': 'john_doe',
    'password': 'secure123'
}

response = requests.post(
    'https://api.example.com/login',
    data=form_data  # Use data for form encoding, not json
)

🔄 Making PUT and PATCH Requests

PUT requests update existing resources. PATCH updates only specific fields.

PUT Request (Replace Entire Resource)

import requests

# Complete replacement
updated_post = {
    'title': 'Updated Title',
    'body': 'Completely new body text',
    'userId': 1
}

response = requests.put(
    'https://jsonplaceholder.typicode.com/posts/1',
    json=updated_post
)

print(f"Updated: {response.json()}")

PATCH Request (Partial Update)

import requests

# Update only specific fields
partial_update = {
    'title': 'Just Update Title'
    # Other fields remain unchanged
}

response = requests.patch(
    'https://jsonplaceholder.typicode.com/posts/1',
    json=partial_update
)

print(f"Patched: {response.json()}")

🗑️ Making DELETE Requests

DELETE requests remove resources from the server.

import requests

# Delete a resource
response = requests.delete('https://jsonplaceholder.typicode.com/posts/1')

# Most APIs return 200 or 204 on successful delete
if response.status_code in [200, 204]:
    print("Resource deleted successfully")
else:
    print(f"Delete failed: {response.status_code}")

📋 Working with Headers

Headers provide additional information about the request and response.

Request Headers

import requests

# Add custom headers
headers = {
    'User-Agent': 'MyPythonApp/1.0',
    'Accept': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN_HERE'
}

response = requests.get(
    'https://api.example.com/users',
    headers=headers
)

Response Headers

import requests

response = requests.get('https://api.github.com/users/octocat')

# Access response headers
print(response.headers['Content-Type'])      # application/json; charset=utf-8
print(response.headers.get('X-RateLimit-Remaining'))  # API rate limit info
print(response.headers)                      # All headers as dictionary

# Common headers to check
for header, value in response.headers.items():
    print(f"{header}: {value}")

🔐 Authentication

Many APIs require authentication. Here are common patterns:

API Key Authentication

import requests

# API key in header
headers = {
    'X-API-Key': 'your-api-key-here'
}
response = requests.get('https://api.example.com/data', headers=headers)

# API key as query parameter
params = {'api_key': 'your-api-key-here'}
response = requests.get('https://api.example.com/data', params=params)

Bearer Token Authentication

import requests

headers = {
    'Authorization': 'Bearer your-jwt-token-here'
}
response = requests.get('https://api.example.com/data', headers=headers)

Basic Authentication

import requests

# Username and password
response = requests.get(
    'https://api.example.com/data',
    auth=('username', 'password')
)

✔️ Checking Response Status

HTTP status codes tell you if the request succeeded:

import requests

response = requests.get('https://api.example.com/users/999')

# Check status
if response.status_code == 200:
    print("Success! Data:", response.json())
elif response.status_code == 404:
    print("Resource not found")
elif response.status_code == 401:
    print("Unauthorized - check your credentials")
elif response.status_code == 500:
    print("Server error")

# Shorthand method
if response.ok:  # True if status is 200-299
    print("Request successful")
else:
    print(f"Request failed: {response.status_code}")

🛡️ Error Handling

Always handle potential errors when making requests:

import requests
from requests.exceptions import RequestException, Timeout, ConnectionError

try:
    # Set timeout to avoid hanging forever
    response = requests.get(
        'https://api.example.com/data',
        timeout=5  # seconds
    )

    # Raise exception if status code indicates error
    response.raise_for_status()

    data = response.json()
    print(f"Success: {data}")

except Timeout:
    print("Request timed out after 5 seconds")
except ConnectionError:
    print("Failed to connect to the server")
except requests.exceptions.HTTPError as e:
    print(f"HTTP error: {e.response.status_code}")
except RequestException as e:
    print(f"Request failed: {e}")

🔄 Working with Response Data

Different APIs return different data formats:

import requests

response = requests.get('https://jsonplaceholder.typicode.com/posts/1')

# Parse JSON
json_data = response.json()
print(json_data['title'])

# Raw text
text_data = response.text
print(text_data[:100])

# Raw bytes (for images, files, etc.)
binary_data = response.content

# Check encoding
print(response.encoding)  # utf-8

# Response size
print(len(response.content))  # bytes

📊 Complete Example: Working with a Real API

import requests
from typing import Dict, List

class PostAPI:
    """Client for JSONPlaceholder Posts API"""

    def __init__(self, base_url='https://jsonplaceholder.typicode.com'):
        self.base_url = base_url

    def get_posts(self, user_id: int = None) -> List[Dict]:
        """Get all posts or posts by specific user"""
        params = {'userId': user_id} if user_id else {}
        response = requests.get(f'{self.base_url}/posts', params=params)
        response.raise_for_status()
        return response.json()

    def get_post(self, post_id: int) -> Dict:
        """Get single post by ID"""
        response = requests.get(f'{self.base_url}/posts/{post_id}')
        response.raise_for_status()
        return response.json()

    def create_post(self, title: str, body: str, user_id: int) -> Dict:
        """Create new post"""
        data = {'title': title, 'body': body, 'userId': user_id}
        response = requests.post(f'{self.base_url}/posts', json=data)
        response.raise_for_status()
        return response.json()

# Using the API client
api = PostAPI()

# Get all posts
all_posts = api.get_posts()
print(f"Total posts: {len(all_posts)}")

# Get posts by user
user_1_posts = api.get_posts(user_id=1)
print(f"User 1 has {len(user_1_posts)} posts")

# Get single post
post = api.get_post(1)
print(f"Post title: {post['title']}")

# Create new post
new_post = api.create_post(
    title='My New Post',
    body='This is awesome!',
    user_id=1
)
print(f"Created post ID: {new_post['id']}")

✅ Key Takeaways

ConceptRemember
GETRetrieve data without changing anything
POSTCreate new resources on server
PUTReplace entire resource
PATCHUpdate specific fields of resource
DELETERemove resource from server
HeadersProvide metadata about request/response
Status Codes2xx = success, 4xx = client error, 5xx = server error
AuthenticationVerify identity using keys, tokens, or credentials
Error HandlingAlways handle timeouts and connection errors

🔗 What's Next?

Learn about HTTP status codes and what they mean for your requests.

Next: Status Codes →


Ready to practice? Try challenges or explore resources


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn