Lesson 23 of 25

Working with APIs

Making HTTP Requests with the requests Library

An API (Application Programming Interface) allows different software systems to communicate. Most modern APIs use HTTP and exchange data in JSON format. Python's 'requests' library makes it simple to interact with APIs.

The most common HTTP methods are GET (retrieve data), POST (send data), PUT (update data), and DELETE (remove data).

Example
import requests

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

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

# GET with query parameters
params = {"userId": 1}
response = requests.get(
    "https://jsonplaceholder.typicode.com/posts",
    params=params
)
posts = response.json()
print(f"User 1 has {len(posts)} posts")

# POST request — send data
new_post = {
    "title": "My New Post",
    "body": "This is the content.",
    "userId": 1
}
response = requests.post(
    "https://jsonplaceholder.typicode.com/posts",
    json=new_post
)
print(f"Created post with id: {response.json()['id']}")
  • requests.get(url) — make a GET request
  • requests.post(url, json=data) — make a POST request with JSON body
  • response.status_code — HTTP status code (200 = OK, 404 = Not Found)
  • response.json() — parse the response body as JSON
  • response.text — get the raw response as a string
  • params={} — add query parameters to the URL
  • headers={} — add custom HTTP headers
Try API Requests
JavaScript
import requests

# Fetch a post
response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
data = response.json()
print(f"Status: {response.status_code}")
print(f"Title: {data['title']}")

# Fetch user info
user = requests.get("https://jsonplaceholder.typicode.com/users/1").json()
print(f"User: {user['name']}")
print(f"Email: {user['email']}")
Notes
  • Always install requests first: 'pip install requests'. It is not part of the standard library but is the most popular HTTP library for Python.

Building a Simple API Client

For repeated API interactions, it's good practice to wrap API calls in a class. This keeps your code organized, handles errors consistently, and makes the API easier to use.

Here's an example of a simple API client class that interacts with a REST API.

Example
import requests

class TodoClient:
    """Simple client for the JSONPlaceholder Todo API"""

    BASE_URL = "https://jsonplaceholder.typicode.com"

    def __init__(self):
        self.session = requests.Session()

    def get_todos(self, user_id=None):
        """Get all todos, optionally filtered by user"""
        params = {}
        if user_id:
            params["userId"] = user_id
        response = self.session.get(f"{self.BASE_URL}/todos", params=params)
        response.raise_for_status()  # Raise exception for HTTP errors
        return response.json()

    def get_todo(self, todo_id):
        """Get a single todo by ID"""
        response = self.session.get(f"{self.BASE_URL}/todos/{todo_id}")
        response.raise_for_status()
        return response.json()

    def create_todo(self, title, user_id, completed=False):
        """Create a new todo"""
        data = {
            "title": title,
            "userId": user_id,
            "completed": completed
        }
        response = self.session.post(f"{self.BASE_URL}/todos", json=data)
        response.raise_for_status()
        return response.json()

# Using the client
client = TodoClient()

# Get a specific todo
todo = client.get_todo(1)
print(f"Todo: {todo['title']}")
print(f"Completed: {todo['completed']}")

# Get user's todos
user_todos = client.get_todos(user_id=1)
print(f"\nUser 1 has {len(user_todos)} todos")
completed = sum(1 for t in user_todos if t["completed"])
print(f"Completed: {completed}/{len(user_todos)}")
Try an API Client
JavaScript
import requests

class TodoClient:
    BASE_URL = "https://jsonplaceholder.typicode.com"

    def get_todos(self, user_id):
        r = requests.get(f"{self.BASE_URL}/todos", params={"userId": user_id})
        return r.json()

client = TodoClient()
todos = client.get_todos(1)
print(f"User 1 has {len(todos)} todos")
for todo in todos[:3]:
    status = "Done" if todo["completed"] else "Pending"
    print(f"  [{status}] {todo['title'][:40]}")
Notes
  • Using requests.Session() is more efficient for multiple requests to the same server. It reuses TCP connections and can persist headers and cookies across requests.