Skip to content
LinkedInX

Python API Basics

About 5 minutes

Target audience: Those who understand Python basics (variables, functions, dictionaries) but have not worked with APIs before
Prerequisites: What is Python, Python Setup

An API call (Application Programming Interface call) is how programs access external services and data. When using AI services and web services with Python, APIs are an essential skill. With the requests library, you can call an API and process the results in just a few lines of code.

APIs exchange data over HTTP (the same protocol used by web browsers). Learn the key HTTP methods:

MethodPurposeExample
GETRetrieve dataGet user information, fetch article list
POSTCreate new dataSend a message, upload a file
PUTUpdate data (full replacement)Update profile information
PATCHPartially update dataChange only the name field
DELETEDelete dataRemove a post

Calls to AI service APIs (Claude, OpenAI, etc.) almost always use POST.

pip install requests

Verify the installation:

import requests
print(requests.__version__)  # e.g., 2.31.0

JSONPlaceholder is a free API for learning and testing. You can send real requests to it.

import requests

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

# Check the HTTP status code
print(response.status_code)  # 200 (success)

# Receive the JSON data as a Python dictionary
data = response.json()
print(data)
# {
#   'userId': 1,
#   'id': 1,
#   'title': 'sunt aut facere repellat...',
#   'body': 'quia et suscipit...'
# }

# Extract specific fields
print(data["title"])
print(data["body"])

You can filter or search results by appending ?key=value to the URL. Use the params argument in requests:

import requests

# Use params instead of manually building the URL
# Actual URL: https://jsonplaceholder.typicode.com/posts?userId=1
response = requests.get(
    "https://jsonplaceholder.typicode.com/posts",
    params={"userId": 1}
)

posts = response.json()
print(f"Number of posts retrieved: {len(posts)}")
for post in posts[:3]:  # Show first 3
    print(f"  - {post['title'][:40]}...")
import requests

# Define the data to send as a dictionary
new_post = {
    "title": "Python API Basics",
    "body": "Learn how to call APIs using the requests library",
    "userId": 1
}

# Send a POST request (using json= auto-sets Content-Type)
response = requests.post(
    "https://jsonplaceholder.typicode.com/posts",
    json=new_post
)

print(response.status_code)  # 201 (created)
created = response.json()
print(f"Created ID: {created['id']}")
ArgumentContent-TypeUse Case
json=dictapplication/jsonREST APIs (AI services, etc.)
data=dictapplication/x-www-form-urlencodedSame format as HTML forms

AI APIs almost always use json=.

APIs do not always succeed. Implement proper error handling:

import requests

response = requests.get("https://jsonplaceholder.typicode.com/posts/999")

if response.status_code == 200:
    print("Success:", response.json())
elif response.status_code == 404:
    print("Not found (404)")
elif response.status_code == 429:
    print("Rate limit reached (429). Please wait before retrying.")
elif response.status_code >= 500:
    print(f"Server error ({response.status_code})")
else:
    print(f"Error: {response.status_code}")

A more concise error checking approach:

import requests

try:
    response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
    response.raise_for_status()  # Raises an exception for 4xx/5xx status codes
    data = response.json()
    print(data["title"])

except requests.exceptions.HTTPError as e:
    print(f"HTTP error: {e}")
except requests.exceptions.ConnectionError:
    print("Network connection error. Please check your internet connection.")
except requests.exceptions.Timeout:
    print("Timeout. The server took too long to respond.")
except requests.exceptions.RequestException as e:
    print(f"Unexpected error: {e}")
import requests

# timeout=(connect_timeout_seconds, read_timeout_seconds)
response = requests.get(
    "https://jsonplaceholder.typicode.com/posts/1",
    timeout=(5, 30)  # 5 seconds to connect, 30 seconds to read
)

Without a timeout, your program will wait forever if the server does not respond. Always set one.

Most APIs require authentication. Include an API key in the request headers:

import requests
import os

# Read API key from environment variable (never write it directly in code)
api_key = os.environ.get("MY_API_KEY")

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
    "User-Agent": "MyApp/1.0"  # Application identifier (optional)
}

response = requests.get(
    "https://api.example.com/data",
    headers=headers,
    timeout=10
)

The pattern of prefixing the key with "Bearer " (Bearer authentication) is the standard format used by many REST APIs including AI APIs.

Using the GitHub public API to retrieve repository information:

import requests
import json

def get_github_repo_info(owner: str, repo: str) -> dict | None:
    """Retrieve basic information for a GitHub repository"""
    url = f"https://api.github.com/repos/{owner}/{repo}"
    headers = {
        "Accept": "application/vnd.github.v3+json",
        "User-Agent": "python-api-tutorial"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return response.json()

    except requests.exceptions.HTTPError as e:
        if response.status_code == 404:
            print(f"Repository not found: {owner}/{repo}")
        else:
            print(f"HTTP error: {e}")
        return None

    except requests.exceptions.RequestException as e:
        print(f"Connection error: {e}")
        return None

def display_repo_info(info: dict) -> None:
    """Display repository information in a readable format"""
    print(f"Repository: {info['full_name']}")
    print(f"Description: {info.get('description', '(no description)')}")
    print(f"Stars: {info['stargazers_count']:,}")
    print(f"Forks: {info['forks_count']:,}")
    print(f"Primary language: {info.get('language', 'Unknown')}")
    print(f"Last updated: {info['updated_at'][:10]}")

# Run it
info = get_github_repo_info("anthropics", "anthropic-sdk-python")
if info:
    display_repo_info(info)

Example output:

Repository: anthropics/anthropic-sdk-python
Description: The official Python library for the Anthropic API
Stars: 4,123
Forks: 456
Primary language: Python
Last updated: 2026-05-10

When making multiple requests to the same host, using requests.Session reuses the TCP connection and improves performance:

import requests

# Create a session
with requests.Session() as session:
    # Set headers shared across all requests in this session
    session.headers.update({
        "Authorization": "Bearer my-api-key",
        "Content-Type": "application/json"
    })

    # Send multiple requests using the same session
    response1 = session.get("https://api.example.com/users/1")
    response2 = session.get("https://api.example.com/users/2")
    response3 = session.post("https://api.example.com/messages", json={"text": "hello"})
  • requests.get() retrieves data; .json() converts the response to a Python dictionary
  • requests.post(url, json=data) sends data
  • Use raise_for_status() and try/except to handle errors properly
  • Read API keys from environment variables; never write them directly in code
  • Always set a timeout
  • Use Session for multiple requests to the same host

As a next step, learn more advanced API response processing in JSON Processing in Python, then move on to AI API calls in Python AI SDK in Practice.

Q: What is the difference between requests and urllib.request?

A: urllib.request is part of the Python standard library and requires no additional installation, but its API is verbose. requests is a third-party library that provides a simpler, more intuitive API. In practice, requests (or async httpx) is widely used.

Q: What should I do when a rate limit (HTTP 429) is hit?

A: A 429 status code is returned. The Retry-After header may specify a wait time. Use time.sleep() to wait and then retry, or use a retry library like tenacity.

Q: How do I call APIs asynchronously?

A: Combine asyncio with the httpx library. This is effective when making multiple API calls in parallel or when integrating with async frameworks like FastAPI.

Q: What should I do if I get an HTTPS certificate error?

A: This can happen when using a corporate proxy or custom CA certificate. Specify the certificate with requests.get(url, verify="/path/to/ca-bundle.crt") or consult your IT department. Never use verify=False in production.

See the references for the external specifications and background sources used on this page.[1][2][3][4]

  1. Requests Official Documentation
  2. JSONPlaceholder (Free learning API)
  3. GitHub REST API
  4. HTTP Status Codes (MDN)