Popular Searches
Popular Course Categories
Popular Courses

Introduction to APIs and HTTP Communication in Python

Introduction to APIs and HTTP Communication in Python

API Integration, Web Scraping, and Automation

Introduction to APIs and HTTP Communication in Python

Course: Python Training

Topic: Introduction to APIs and HTTP Communication in Python

Course Link: Python Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy Homepage


1. Introduction to APIs

An API (Application Programming Interface) is a set of rules and conventions that allows two software applications to communicate with each other. It defines how one application can request data or functionality from another application without needing to understand its internal implementation.

For example, a Python application can communicate with a weather service API to retrieve the current temperature of a city. The API receives the request, processes it, and returns the result in a structured format such as JSON.

Real-World Examples of APIs

  • Weather APIs: Provide temperature, humidity, forecasts, and weather alerts.
  • Payment APIs: Enable applications to integrate online payment services.
  • Maps APIs: Provide location, distance, navigation, and geographical data.
  • Social media APIs: Allow authorized applications to access supported platform features.
  • Authentication APIs: Support user identity verification and access management.
  • E-commerce APIs: Provide product information, order details, inventory, and shipping information.

Why Are APIs Important?

  • They allow applications built with different technologies to communicate.
  • They enable developers to reuse existing services and functionality.
  • They reduce development time and duplication of work.
  • They support integrations between websites, mobile applications, and external services.
  • They help separate application components into manageable services.
  • They make it easier to exchange data between different systems.

2. How an API Works

Most web APIs follow a client-server communication model. The client requests information or an operation, and the server processes the request and sends a response.

  1. Client: The application that needs information or wants to perform an operation.
  2. Request: The client sends an HTTP request to an API endpoint.
  3. Server: The server receives the request and checks its validity and permissions.
  4. Processing: The server performs the requested operation, potentially accessing a database or another service.
  5. Response: The server returns an HTTP status code and, when appropriate, response data.
  6. Client handling: The client examines the response and uses the returned information.

API Communication Flow

Python Client
     |
     | HTTP Request
     v
API Server
     |
     | Validate and Process Request
     v
Database or External Service
     |
     | Return Result
     v
API Server
     |
     | HTTP Response (JSON)
     v
Python Client

Python can act as an API client when consuming external services. It can also act as an API server when exposing functionality through frameworks such as Flask or FastAPI.

3. Understanding HTTP

HTTP stands for Hypertext Transfer Protocol. It is an application-layer protocol used to exchange information between clients and servers. Web browsers, mobile applications, and Python programs commonly use HTTP to communicate with web servers.

HTTPS is HTTP protected by Transport Layer Security (TLS). When correctly configured, HTTPS encrypts data in transit and helps authenticate the server.

Important Characteristics of HTTP

  • Request-response model: A client sends a request and receives a response.
  • Statelessness: HTTP does not automatically remember previous requests. Applications can maintain state using sessions, cookies, tokens, or server-side storage.
  • Methods: HTTP supports methods such as GET, POST, PUT, PATCH, and DELETE.
  • Headers: Requests and responses can contain metadata about content, authentication, caching, and other behavior.
  • Status codes: Responses communicate whether a request succeeded or encountered an error.

4. Structure of an HTTP Request

An HTTP request generally contains a method, a URL or target path, headers, and optionally a request body.

Component Description Example
HTTP method Indicates the intended operation. GET, POST
URL or endpoint Identifies the resource or operation. https://api.example.com/users
Headers Provide request metadata. Accept: application/json
Query parameters Pass filtering or search values in the URL. ?page=1&limit=10
Request body Contains data submitted to the server. A JSON object

Example HTTP Request

GET /users?page=1 HTTP/1.1
Host: api.example.com
Accept: application/json

This request asks the server for the first page of users and indicates that the client prefers JSON data. The example domain is illustrative and is not a working API endpoint.

5. Structure of an HTTP Response

An HTTP response is sent by the server after processing a request. It usually contains a status code, response headers, and an optional response body.

Component Purpose
Status code Indicates the result of the request.
Response headers Describe the content and provide response metadata.
Response body Contains returned data, an error message, or other content when provided.

Example JSON Response

{
    "id": 101,
    "name": "Aarav",
    "email": "[email protected]"
}

This response contains a user object. The client can parse the JSON and access individual fields using Python dictionary syntax.

6. Common HTTP Methods

HTTP methods indicate the intended action for a resource. The API determines which methods are supported by each endpoint.

Method Purpose Example
GET Retrieve information. Fetch a list of products.
POST Submit data or create a resource. Create a customer record.
PUT Replace a resource representation. Replace a complete user profile.
PATCH Partially update a resource. Change a user's email address.
DELETE Request removal of a resource. Delete a product.

Important: GET should not be used for operations intended to modify server-side data. PUT is generally designed to be idempotent, meaning repeating the same request should have the same intended effect. POST is not generally idempotent by default. Actual behavior depends on the API's implementation.

7. HTTP Status Codes

HTTP status codes indicate the outcome of a request. They are divided into five main categories.

Range Category Examples
100–199 Informational 100 Continue
200–299 Success 200 OK, 201 Created, 204 No Content
300–399 Redirection 301 Moved Permanently, 304 Not Modified
400–499 Client errors 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests
500–599 Server errors 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable

Frequently Used Status Codes

  • 200 OK: The request succeeded.
  • 201 Created: A resource was created successfully.
  • 204 No Content: The request succeeded without a response body.
  • 400 Bad Request: The request is invalid or cannot be processed.
  • 401 Unauthorized: Valid authentication credentials are missing or invalid.
  • 403 Forbidden: The server refuses to authorize the requested operation.
  • 404 Not Found: The resource or endpoint could not be found.
  • 429 Too Many Requests: The client exceeded a request limit.
  • 500 Internal Server Error: The server encountered an unexpected problem.

8. Understanding JSON in Python APIs

JSON stands for JavaScript Object Notation. It is a lightweight text-based format used to exchange structured data between applications. JSON is widely used by web APIs because it is readable and supported by many programming languages.

JSON Data Types

  • String: "Python"
  • Number: 25 or 19.5
  • Boolean: true or false
  • Null: null
  • Array: ["Python", "SQL", "Flask"]
  • Object: {"name": "Aarav", "age": 25}

Convert Python Data into JSON

import json
 
student = {
    "name": "Aarav",
    "course": "Python",
    "completed": True
}
 
json_text = json.dumps(student)
print(json_text)

Convert JSON into Python Data

import json
 
json_text = '{"name": "Aarav", "age": 25}'
 
student = json.loads(json_text)
 
print(student["name"])
print(student["age"])

Python's json module converts JSON objects into dictionaries, arrays into lists, and JSON Boolean and null values into the corresponding Python values. Python uses True, False, and None, while JSON uses true, false, and null.

9. Setting Up Python for HTTP Communication

Python includes standard-library tools for network communication. However, the third-party Requests library is a popular choice because it makes common HTTP operations straightforward.

Step 1: Check Python Installation

python --version

Step 2: Install the Requests Library

python -m pip install requests

If your environment uses the python3 command, use python3 -m pip install requests where appropriate. A virtual environment is recommended for managing project dependencies.

Step 3: Import Requests

import requests

10. Making a GET Request

A GET request retrieves information from an API. It is commonly used to fetch user details, products, articles, weather information, and other resources.

Example: Retrieve a Post

import requests
 
url = "https://jsonplaceholder.typicode.com/posts/1"
 
try:
    response = requests.get(url, timeout=10)
    response.raise_for_status()
 
    post = response.json()
 
    print("Post ID:", post["id"])
    print("Title:", post["title"])
    print("Body:", post["body"])
 
except requests.exceptions.Timeout:
    print("The request timed out.")
 
except requests.exceptions.HTTPError as error:
    print("HTTP error:", error)
 
except requests.exceptions.RequestException as error:
    print("Request failed:", error)

Explanation

  • requests.get(url) sends an HTTP GET request.
  • timeout=10 configures connection and response waiting limits.
  • raise_for_status() raises an HTTP error for unsuccessful status codes.
  • response.json() parses a valid JSON response into Python data.
  • The try and except blocks help handle request failures.

JSONPlaceholder is a public testing API. It is useful for learning, but its behavior and availability are not guaranteed. Consult the documentation of the actual API you intend to use.

11. Inspecting the HTTP Response

The Requests response object provides useful properties for understanding the server's reply.

import requests
 
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url, timeout=10)
 
print("Status code:", response.status_code)
print("Response URL:", response.url)
print("Content type:", response.headers.get("Content-Type"))
print("Response text:", response.text[:200])
Property or Method Description
response.status_code Returns the HTTP status code.
response.headers Provides response headers.
response.text Returns the response body as text.
response.content Returns the response body as bytes.
response.json() Parses a JSON response.
response.url Provides the final response URL.
response.raise_for_status() Raises an exception for unsuccessful HTTP status codes.

Do not assume every response contains valid JSON. A server may return an empty response, HTML error page, or plain text. Check the status code and content type when necessary.

12. Sending Query Parameters

Query parameters are used to filter, search, sort, or paginate API results. They appear in the URL after a question mark, with multiple parameters separated by ampersands.

For example, https://api.example.com/products?category=books&limit=10 requests products in the books category with a limit of ten, assuming the API supports those parameters.

Python Example

import requests
 
url = "https://jsonplaceholder.typicode.com/posts"
 
params = {
    "userId": 1,
    "_limit": 5
}
 
response = requests.get(
    url,
    params=params,
    timeout=10
)
 
response.raise_for_status()
posts = response.json()
 
for post in posts:
    print(post["id"], post["title"])

Using the params argument is generally safer and more convenient than manually constructing a URL because Requests handles URL encoding.

13. Sending HTTP Headers

Headers carry metadata about a request. APIs may require headers to specify the expected response format, identify the client, or provide authentication credentials.

import requests
 
url = "https://api.example.com/profile"
 
headers = {
    "Accept": "application/json",
    "User-Agent": "PythonLearningApp/1.0"
}
 
response = requests.get(
    url,
    headers=headers,
    timeout=10
)
 
print("Status code:", response.status_code)

The endpoint above is an illustrative placeholder. Common headers include:

  • Accept: Specifies the response content types the client can accept.
  • Content-Type: Describes the format of the request body.
  • Authorization: Carries authentication credentials when required.
  • User-Agent: Identifies the client application.
  • Cache-Control: Communicates caching preferences or requirements.

14. Sending POST Requests with JSON

POST requests are often used to submit information or create a resource. The Requests library can automatically convert a Python dictionary to JSON using the json argument.

import requests
 
url = "https://jsonplaceholder.typicode.com/posts"
 
new_post = {
    "title": "Learning Python APIs",
    "body": "Practicing HTTP communication with Requests.",
    "userId": 1
}
 
try:
    response = requests.post(
        url,
        json=new_post,
        timeout=10
    )
 
    response.raise_for_status()
 
    if response.content:
        print(response.json())
    else:
        print("The request succeeded without a response body.")
 
except requests.exceptions.RequestException as error:
    print("Request failed:", error)

Why Use the JSON Argument?

  • It serializes the Python object into JSON.
  • It sets the appropriate JSON content type.
  • It makes the request easier to read and maintain.

JSONPlaceholder is a testing service and may simulate record creation rather than permanently storing data. Real APIs may require authentication, validation, and additional fields.

15. Understanding PUT, PATCH, and DELETE

PUT Request

PUT is commonly used to replace a resource representation.

import requests
 
url = "https://api.example.com/users/10"
 
updated_user = {
    "name": "Aarav Sharma",
    "email": "[email protected]"
}
 
response = requests.put(
    url,
    json=updated_user,
    timeout=10
)
 
print(response.status_code)

PATCH Request

PATCH is commonly used to update selected fields of an existing resource.

import requests
 
url = "https://api.example.com/users/10"
 
changes = {
    "email": "[email protected]"
}
 
response = requests.patch(
    url,
    json=changes,
    timeout=10
)
 
print(response.status_code)

DELETE Request

DELETE requests ask the server to remove a resource or make it unavailable according to the API's design.

import requests
 
url = "https://api.example.com/users/10"
 
response = requests.delete(url, timeout=10)
 
print("Status code:", response.status_code)

These endpoints are examples only. Use real modification and deletion requests only when you are authorized to access the service and understand the consequences.

16. API Authentication

Many APIs protect their data and operations through authentication. Authentication identifies the caller, while authorization determines which resources or actions that caller is allowed to access.

Common Authentication Methods

  • API key: A key used to identify an application or client.
  • Bearer token: A token commonly sent in the Authorization header.
  • OAuth 2.0: An authorization framework that supports controlled access to protected resources.
  • Basic authentication: Sends a username and password encoded using Base64. It should only be used over HTTPS and when supported by the API.
  • Session-based authentication: Uses session identifiers, often stored in cookies.

Example: Bearer Token Authentication

import os
import requests
 
token = os.environ.get("API_TOKEN")
 
if not token:
    raise RuntimeError("Set the API_TOKEN environment variable.")
 
headers = {
    "Authorization": f"Bearer {token}",
    "Accept": "application/json"
}
 
response = requests.get(
    "https://api.example.com/profile",
    headers=headers,
    timeout=10
)
 
response.raise_for_status()
print(response.json())

The URL is a placeholder for an authenticated API endpoint. Store real credentials in environment variables or a secrets manager. Do not hard-code tokens into source files or publish them in public repositories.

17. Using Sessions in Requests

A Requests session can reuse connections and preserve cookies and configuration across multiple requests. Sessions are useful when an API requires related requests to share cookies or common headers.

import requests
 
with requests.Session() as session:
    session.headers.update({
        "Accept": "application/json"
    })
 
    first_response = session.get(
        "https://jsonplaceholder.typicode.com/posts/1",
        timeout=10
    )
    first_response.raise_for_status()
 
    second_response = session.get(
        "https://jsonplaceholder.typicode.com/posts/2",
        timeout=10
    )
    second_response.raise_for_status()
 
    print(first_response.json()["title"])
    print(second_response.json()["title"])

A session does not automatically authenticate a user. Authentication details must be configured according to the API's requirements.

18. Error Handling in API Communication

API requests can fail because of connection problems, timeouts, invalid URLs, authentication errors, rate limits, or server failures. Proper error handling prevents an application from crashing unexpectedly and helps developers diagnose problems.

Exception Possible Cause Recommended Action
Timeout The connection or response took too long. Check service performance and consider a safe retry.
ConnectionError The connection could not be established or was interrupted. Check connectivity, DNS, and service availability.
HTTPError An unsuccessful HTTP status code was raised. Inspect the status code and API error details.
RequestException A general Requests-related failure occurred. Handle as a broader request error.
JSONDecodeError The response body is not valid JSON. Check the response body and content type.

Example: Robust Error Handling

import requests
 
url = "https://jsonplaceholder.typicode.com/posts/1"
 
try:
    response = requests.get(url, timeout=10)
    response.raise_for_status()
 
    try:
        data = response.json()
        print("Title:", data["title"])
    except requests.exceptions.JSONDecodeError:
        print("The server did not return valid JSON.")
 
except requests.exceptions.Timeout:
    print("The request timed out.")
 
except requests.exceptions.HTTPError as error:
    print("HTTP error:", error)
 
except requests.exceptions.ConnectionError:
    print("Could not connect to the API.")
 
except requests.exceptions.RequestException as error:
    print("Request failed:", error)

Use exception classes supported by your installed Requests version. Keep error messages useful, but do not expose credentials, tokens, private user data, or sensitive server details in logs.

19. Timeouts, Retries, and Rate Limits

Timeouts

A timeout prevents a client from waiting indefinitely for a connection or response. Requests accepts a single timeout value or a tuple specifying connection and read timeouts.

response = requests.get(
    "https://jsonplaceholder.typicode.com/posts/1",
    timeout=(3, 10)
)

Here, the connection timeout is 3 seconds and the read timeout is 10 seconds. A read timeout generally limits how long the client waits between received bytes; it is not necessarily a strict total deadline for the entire operation.

Retries

Retries can help recover from temporary failures. However, they must be configured carefully. Repeating a request that changes data can accidentally create duplicate records or repeat an operation. Prefer retrying safe operations and follow the API's documented retry rules.

Rate Limits

Rate limits restrict the number of requests allowed within a time period. A server may return 429 Too Many Requests when a client exceeds the limit.

  • Check the API's rate-limit documentation.
  • Respect the Retry-After header when provided.
  • Avoid sending repeated requests unnecessarily.
  • Use caching and pagination where appropriate.

20. Working with API Pagination

Pagination divides a large collection into smaller responses. APIs may use page numbers, offsets, cursors, or next-page URLs to support pagination.

Example: Page-Based Pagination

import requests
 
base_url = "https://api.example.com/products"
page = 1
page_size = 20
 
while True:
    params = {
        "page": page,
        "limit": page_size
    }
 
    response = requests.get(
        base_url,
        params=params,
        timeout=10
    )
    response.raise_for_status()
 
    products = response.json()
 
    if not products:
        break
 
    for product in products:
        print(product)
 
    if len(products) < page_size:
        break
 
    page += 1

This is an illustrative example that assumes the API returns a list of products for each page. Actual APIs may return a JSON object with fields such as items, next, or next_cursor. Always follow the API's pagination documentation.

21. Validating API Response Data

Data returned by an external API should not be assumed to be complete or correctly formatted. Validate required fields and data types before using the information in your application.

def get_user_name(user_data):
    if not isinstance(user_data, dict):
        raise ValueError("Expected a dictionary.")
 
    name = user_data.get("name")
 
    if not isinstance(name, str) or not name.strip():
        raise ValueError("A valid name is required.")
 
    return name.strip()
 
 
example_user = {
    "id": 101,
    "name": "Aarav"
}
 
print(get_user_name(example_user))

Validation helps prevent errors caused by missing keys, unexpected data types, and malformed values. Larger projects can use validation libraries or typed data models to manage complex responses.

22. Introduction to REST APIs

REST stands for Representational State Transfer. It is an architectural style commonly used for designing web APIs around resources. REST-style APIs often use URLs to identify resources and HTTP methods to express operations.

Endpoint Method Typical Purpose
/products GET Retrieve a list of products.
/products/25 GET Retrieve product 25.
/products POST Create a product.
/products/25 PUT Replace product 25.
/products/25 PATCH Update selected fields of product 25.
/products/25 DELETE Delete product 25.

These examples demonstrate common conventions rather than universal rules. Not every HTTP API follows all REST architectural constraints.

23. Creating a Simple API Using Flask

Python can be used to build API servers as well as consume external APIs. Flask is a lightweight web framework that allows developers to create routes and return JSON responses.

Install Flask

python -m pip install flask

Example Flask API

from flask import Flask, jsonify
 
app = Flask(__name__)
 
products = [
    {"id": 1, "name": "Keyboard", "price": 1200},
    {"id": 2, "name": "Mouse", "price": 650},
    {"id": 3, "name": "Monitor", "price": 8500}
]
 
@app.get("/api/products")
def get_products():
    return jsonify(products)
 
@app.get("/api/products/<int:product_id>")
def get_product(product_id):
    for product in products:
        if product["id"] == product_id:
            return jsonify(product)
 
    return jsonify({"error": "Product not found"}), 404
 
if __name__ == "__main__":
    app.run(debug=True)

Run the Application

  1. Save the code in a file named app.py.
  2. Install Flask using python -m pip install flask.
  3. Run the application using python app.py.
  4. Visit http://127.0.0.1:5000/api/products to retrieve all products.
  5. Visit http://127.0.0.1:5000/api/products/1 to retrieve a specific product.

The application stores example products in memory, so the data is not persistent. Debug mode is intended for local development only. Use a suitable production server and secure configuration when deploying a real application.

24. API Security Best Practices

  • Use HTTPS: Protect data and credentials during transmission.
  • Protect API keys: Store secrets in environment variables or a secrets manager.
  • Validate input: Check data received from users and external services.
  • Apply authorization: Verify that users have permission to access or modify requested resources.
  • Use least privilege: Give applications only the permissions they need.
  • Handle errors safely: Avoid exposing internal stack traces or sensitive implementation details.
  • Respect rate limits: Avoid excessive requests and follow server retry instructions.
  • Keep dependencies updated: Use maintained libraries and install security updates.
  • Verify TLS certificates: Do not disable certificate verification in production code.
  • Protect logs: Avoid recording passwords, tokens, and sensitive personal information.

25. Common API Communication Problems

Problem Possible Cause Solution
Connection error Network, DNS, or server problem. Check connectivity, hostname, and service availability.
Timeout The connection or response takes too long. Configure suitable timeouts and investigate service performance.
401 Unauthorized Missing or invalid credentials. Check the authentication requirements.
403 Forbidden The caller lacks permission. Review authorization rules and access rights.
404 Not Found Incorrect endpoint or missing resource. Verify the URL, resource ID, and API version.
429 Too Many Requests Rate limit exceeded. Reduce request frequency and follow retry instructions.
500-series error Server-side or upstream failure. Check service status and retry safely when appropriate.
JSON parsing error The response is empty or contains invalid JSON. Inspect the response body, status, and content type.

26. Practical Exercises

Exercise 1: Fetch a Post

  • Send a GET request to https://jsonplaceholder.typicode.com/posts/1.
  • Print the status code, title, and body.
  • Handle network errors and unsuccessful HTTP responses.

Exercise 2: Retrieve Multiple Records

  • Retrieve posts using the userId query parameter.
  • Print the ID and title of every returned post.
  • Experiment with different query parameter values.

Exercise 3: Send JSON Data

  • Create a Python dictionary containing a title, body, and user ID.
  • Submit it using a POST request and the json argument.
  • Inspect the status code and response body.

Exercise 4: Create a Flask API

  • Create an API that returns a list of books or products.
  • Add an endpoint that retrieves a record by ID.
  • Return a 404 response if the requested record does not exist.

Exercise 5: Improve Reliability

  • Add a timeout to every outgoing request.
  • Handle connection errors and unsuccessful HTTP responses.
  • Validate required fields in the returned JSON.
  • Ensure sensitive information is not printed in logs.

27. Interview Questions and Answers

Q1. What is an API?

Answer: An API is an interface that defines how software components communicate and exchange data or functionality.

Q2. What is HTTP?

Answer: HTTP is an application-layer protocol used for communication between clients and servers.

Q3. What is the difference between HTTP and HTTPS?

Answer: HTTPS uses TLS to protect HTTP communication through encryption and server authentication. Plain HTTP does not provide TLS protection.

Q4. What is a REST API?

Answer: A REST API is designed around REST architectural principles, commonly using resource-oriented endpoints and HTTP methods.

Q5. What is JSON?

Answer: JSON is a text-based format used to exchange structured data between applications.

Q6. How do you make an HTTP request in Python?

Answer: One common method is to use Requests, such as requests.get(url, timeout=10).

Q7. What does raise_for_status() do?

Answer: It raises an HTTP error when the response has an unsuccessful HTTP status code.

Q8. What is the difference between GET and POST?

Answer: GET is generally used to retrieve information, whereas POST is commonly used to submit data or create resources.

Q9. Why should API requests have timeouts?

Answer: Timeouts prevent an application from waiting indefinitely for a connection or response.

Q10. What is an API endpoint?

Answer: An endpoint is a URL or URL path through which a client accesses a particular resource or API operation.

Q11. What does HTTP 404 mean?

Answer: It means the requested resource or endpoint could not be found.

Q12. How can you protect an API token in Python?

Answer: Store it in an environment variable or secrets manager, avoid committing it to source control, and never expose it in logs or public responses.

28. Quick Revision Checklist

  • Understand what APIs are and how clients communicate with servers.
  • Know the structure of HTTP requests and responses.
  • Understand GET, POST, PUT, PATCH, and DELETE methods.
  • Recognize common HTTP status codes.
  • Understand JSON and Python's JSON support.
  • Install and use the Requests library.
  • Send query parameters, headers, and JSON bodies.
  • Inspect responses and handle HTTP errors.
  • Use timeouts and configure retries carefully.
  • Understand authentication, pagination, and rate limits.
  • Recognize common REST API patterns.
  • Create a basic API using Flask.
  • Apply security and data validation best practices.

29. Conclusion

APIs and HTTP communication are essential concepts for Python developers working with web applications, automation, data integration, and backend services. Understanding requests, responses, HTTP methods, status codes, JSON, authentication, and error handling makes it possible to build reliable API clients and services.

Start by retrieving data from a public testing API, then practise sending JSON requests, handling failures, and creating a small Flask API. These exercises establish a strong foundation for advanced topics such as database integration, OAuth, asynchronous requests, and production deployment.

30. Additional Learning Resources

whatsapp