March 25, 2025

How to Use an API in Python

Want to know exactly where the International Space Station is orbiting right now? Pull live tweets about your favorite topic? Get real-time stock prices? You can do all of this with just a few lines of code, if you know how to use an API in Python!

View of the International Space Station orbiting Earth, showcasing real-time data possibilities with APIs
The International Space Station: A source of real-time data via APIs

This is the power of APIs. They let you pull data from platforms like Reddit, Twitter, and Facebook straight into your Python projects.

Whether you're building a beginner project, exploring data science, or working with AI, APIs are an essential skill for data professionals.

In this guide, we'll start simple. You'll learn to retrieve data from the ISS. Then we'll move to more advanced techniques like sending data and handling errors.

What is an API?

An API (application programming interface) is a server that lets you request and send data using code. It works as a bridge between your app and external systems.

You get valuable data without having to gather it manually.

Think of an API as a waiter at a restaurant. You tell the waiter what you want. They take your order to the kitchen. The kitchen prepares your food. The waiter brings it back to you.

When you work with a Python API, you send a request to an API server. It processes your request. Then it sends back the results.

Understanding API Endpoints

When you work with an API, you don't just send a request to the whole API server. You send it to a specific endpoint. An endpoint is like a specific URL address that does one particular thing.

For example, a weather API might have one endpoint for current weather and a different endpoint for forecasts. Each endpoint has its own URL and returns different data.

Popular Tools that Use APIs

Here are some widely used APIs that show the power of working with APIs in Python:

  • OpenAI API: A tool for text generation, summarization, and understanding language.
  • Google Cloud AI APIs: Provides vision, language, and conversational AI services.
  • IBM Watson API: A suite of tools for tasks like NLP and visual recognition.

Understanding HTTP Methods in Python APIs

Before we dive into code, let's talk about the different types of requests you can make to an API.

APIs use HTTP methods (sometimes called HTTP verbs) to say what action you want to perform:

  • GET: Gets data from an API server without changing anything. When you check the weather, look up stock prices, or search for tweets, you're using GET requests. It's the most common method. We'll focus on it first.
  • POST: Sends data to an API to create new things. This happens when you post a tweet, submit a contact form, or upload a photo.
  • PUT: Updates existing data on the server by replacing it. If you edit your profile or update a blog post, that's usually a PUT request.
  • DELETE: Removes data from the server. This one does exactly what it sounds like.

For most data retrieval tasks, you'll work with GET requests. POST requests become important when you need to send data somewhere. We'll cover that later in this tutorial.

Understanding these HTTP methods helps you pick the right tool for what you're trying to do.

Why and When to Use an API in Python

Using an API in Python offers several advantages for AI and data science projects:

  • Real-time data access: Get up-to-date data on demand. This is key for projects that need timely information.
  • Access to large datasets: APIs make it easy to get data from multiple sources. You don't need huge storage space or manual work.
  • Pre-processed insights: Many APIs give you enriched data. Things like sentiment analysis or key entity recognition. This saves time on data prep.

When APIs Are Better Than Static Datasets

APIs work especially well in these situations:

  • Fast-changing data: For information that changes often, APIs save you from downloading and updating files over and over.
  • Targeted data: Get only the specific part of a dataset you need. Like recent Reddit comments or specific stock prices.
  • Special computations: APIs like Spotify's provide unique insights like genre classifications, song mood, and danceability scores. They've already done the heavy analysis work on millions of songs, so you get instant results without needing powerful computers or complex algorithms yourself.

How APIs Enhance Python Projects

Working with an API in Python opens up opportunities to create smarter apps. For example:

  • Using Pre-Built AI Models: Add advanced NLP or computer vision models to your projects. You don't have to build them from scratch.
  • Getting Data Easily: Pull data from platforms like Reddit, Facebook, or financial services. Use it for analysis or machine learning projects.
  • Using AI Services: APIs give you access to features like sentiment analysis, language translation, or image recognition. You can build strong solutions quickly.

Preparing Your Python Environment for APIs

To work with an API in Python, we need a tool for making API requests.

The most common library is the requests library. It makes API usage simple with an easy interface.

Since requests isn't included in standard Python, we need to install it first.

If you use pip to manage your Python packages, install the requests library with this command from your terminal:

pip install requests

If you're using conda, use this command instead:

conda install requests

Once installed, import the library into your Python script:

import requests

Making Your First API Request in Python

Now that we've set up the requests library, let's make our first API request.

We'll start with a simple GET request. Then we'll look at the status codes that come with the response.

APIs use different request types. GET is by far the most common when we just need to get data. Since we're focusing on pulling information from APIs, we'll mostly use GET requests in this Python API tutorial.

Illustration of an API request and response showing how data flows between a client and server

A typical API request involves sending a query to the server and receiving a response.

When we make an API call, the response includes a status code. This tells us if the request worked or if something went wrong.

Let's try making a GET request to an API endpoint that doesn't exist. We'll see what an error status code looks like.

Here's how we do it using the requests.get() function:

response = requests.get("http://api.open-notify.org/this-api-doesnt-exist")
print(response.status_code)
404

The 404 status code probably looks familiar. It's what a server returns when it can't find what we're asking for.

In this example, we asked for this-api-doesnt-exist. As expected, it doesn't exist. This helps us understand what an error response looks like.

Understanding Common API Status Codes

Every API request to a web server returns a status code. It shows the outcome of the request.

Here are some common codes for GET and POST requests:

  • 200: Everything worked. The result has been returned (if any).
  • 201: A new resource was created (common with POST requests).
  • 301: The server is sending you to a different API endpoint. This can happen when a company switches domain names.
  • 400: The server thinks you made a bad request. This happens when you send wrong data.
  • 401: The server thinks you're not logged in. Many APIs need credentials.
  • 403: The resource is forbidden. You don't have the right permissions.
  • 404: The resource wasn't found on the server.
  • 503: The server isn't ready to handle the request.

Status codes starting with 4 mean client-side errors. Codes starting with 5 mean server-side issues.

The first digit helps you quickly see if a request worked (2xx) or if there was an error (4xx or 5xx).

Read more about status codes here to learn more.

Now you understand the basics of API requests and status codes. You're ready to start making your own requests!

How to Read API Documentation (and Why It Matters)

Checking Documentation for Good API Requests

When working with APIs, checking the documentation is essential. This is especially true for AI and data science work.

Documentation from providers like OpenAI, Google Cloud AI, or IBM Watson shows how to use their services well. Good API reference materials save you time and prevent common mistakes.

Key Parts of API Documentation

Most API documentation includes details on available API endpoints. It shows required parameters, authentication methods, and expected response formats.

For example, the OpenAI API documentation gives guidance on using their language models. Like GPT-4 for natural language processing tasks.

Exploring the Open Notify API

Here, we'll work with the Open Notify API. It provides data about the International Space Station.

This API is great for beginners. It has a simple design and doesn't need authentication. Perfect for learning Python API basics.

Understanding API Endpoints

APIs often offer multiple API endpoints for different types of data.

We'll start with the http://api.open-notify.org/astros.json endpoint. It returns information about astronauts currently in space.

According to the documentation, this API needs no input parameters. That makes it simple to use.

Making a GET Request to the API

Let's make a GET request to this API endpoint using the requests library:

response = requests.get("http://api.open-notify.org/astros")
print(response.status_code)
200

The 200 status code means our API call worked. The API response is in JSON format.

To view the data, we'll use the response.json() method:

print(response.json())
{'people': [{'craft': 'ISS', 'name': 'Oleg Kononenko'},
{'craft': 'ISS', 'name': 'Nikolai Chub'},
{'craft': 'ISS', 'name': 'Tracy Caldwell Dyson'},
{'craft': 'ISS', 'name': 'Matthew Dominick'},
{'craft': 'ISS', 'name': 'Michael Barratt'},
{'craft': 'ISS', 'name': 'Jeanette Epps'},
{'craft': 'ISS', 'name': 'Alexander Grebenkin'},
{'craft': 'ISS', 'name': 'Butch Wilmore'},
{'craft': 'ISS', 'name': 'Sunita Williams'},
{'craft': 'Tiangong', 'name': 'Li Guangsu'},
{'craft': 'Tiangong', 'name': 'Li Cong'},
{'craft': 'Tiangong', 'name': 'Ye Guangfu'}],
'number': 12, 'message': 'success'}

Look at that! We just got real, live data about who's in space right now. The response shows 12 people currently aboard the ISS and Tiangong space stations.

The data comes back as a Python dictionary. This means we can easily work with it. We could count the astronauts, filter by spacecraft, or save the names to a file.


Working with JSON Data in Python

What is JSON?

JSON (JavaScript Object Notation) is widely used in APIs. It encodes data structures so machines can read them easily.

APIs mostly exchange data in JSON format. This makes it a cornerstone for modern data apps. When working with Python APIs, you'll see JSON data constantly.

JSON in AI and Data Science

In AI and data science, JSON helps systems exchange data smoothly. Many APIs use JSON as the standard format for requests and responses. APIs from OpenAI, Google Cloud AI, and IBM Watson all use it.

This makes it easy to add API features to Python apps. Knowing how to work with JSON data is essential for good API work.

When APIs send data, they send it as JSON text. JSON looks very similar to Python dictionaries and lists, which is why it's so easy to work with in Python.

Here's the key thing: JSON is just text. But it's formatted in a way that looks like Python data structures. That's why when we call response.json(), Python can easily convert it into actual dictionaries and lists we can use.

JSON format illustration showing key-value pairs and data structure

Working with JSON in Python

Python's built-in json package offers strong JSON support. This library lets us convert between JSON strings and Python objects easily.

For example, the JSON data about astronauts can be turned into a Python dictionary.

The json library has two key functions:

Using dumps(), we can format JSON data so it's easier to read:

import json

# create a formatted string of the Python JSON object
def jprint(obj):
    text = json.dumps(obj, sort_keys=True, indent=4)
    print(text)

jprint(response.json())

Looking at the API Response

{
    "message": "success",
    "number": 12,
    "people": [
        {
            "craft": "ISS",
            "name": "Oleg Kononenko"
        },
        {
            "craft": "ISS",
            "name": "Nikolai Chub"
        },
        {
            "craft": "ISS",
            "name": "Tracy Caldwell Dyson"
        },
        {
            "craft": "ISS",
            "name": "Matthew Dominick"
        },
        {
            "craft": "ISS",
            "name": "Michael Barratt"
        },
        {
            "craft": "ISS",
            "name": "Jeanette Epps"
        },
        {
            "craft": "ISS",
            "name": "Alexander Grebenkin"
        },
        {
            "craft": "ISS",
            "name": "Butch Wilmore"
        },
        {
            "craft": "ISS",
            "name": "Sunita Williams"
        },
        {
            "craft": "Tiangong",
            "name": "Li Guangsu"
        },
        {
            "craft": "Tiangong",
            "name": "Li Cong"
        },
        {
            "craft": "Tiangong",
            "name": "Ye Guangfu"
        }
    ]
}

The formatted output shows that 12 people are currently in space. Their names are stored as JSON objects inside a list. This JSON data structure makes the information easy to work with in Python.

Compare this output with the documentation for the endpoint. You'll see it matches the expected structure.

JSON's simplicity makes it a must-have tool for exchanging data in AI and data science projects. It provides a universal format. This means different systems can work together. Developers can get the most from multiple APIs.

Using Query Parameters with APIs in Python

The http://api.open-notify.org/astros.json endpoint we used earlier doesn't need any parameters. We just send a GET request. The API returns data about people in space.

But many APIs need query parameters to customize their behavior. This is especially common in APIs for AI and data science.

Query parameters let us access specific subsets of data. We can configure AI models or refine results. Knowing how to use query parameters well is key for advanced API work in Python.

What Is a Query Parameter?

Query parameters are a way to filter and customize the data an API returns.

For example, you might use a query parameter to get data for a specific region, date range, or category. They're the options you pass to an API to get exactly what you need.

Understanding Query Parameter Syntax

When you look at API documentation or check network requests in your browser, you'll see URLs with query parameters.

Here's what they look like:

https://api.example.com/weather?city=London&units=metric

Let's break down what each part means:

  • ?: Marks the start of query parameters in the URL
  • city=London: The first parameter (city) and its value (London)
  • &: Separates multiple query parameters
  • units=metric: The second parameter (units) and its value (metric)

Being able to read this syntax is useful. You'll see it in API documentation, error messages, and when debugging.

But when you're actually writing Python code, you won't need to build these URLs manually.

Exploring the World Bank's Development Indicators API

For this example, we'll use the World Bank's Development Indicators. It's a database with global development data for 265 countries.

To make access easier, we built a dedicated API server. It's at https://api-server.dataquest.io/economic_data. This makes querying simpler in our examples.

Making a Request Without a Query Parameter

First, let's see what happens when we make a request without using a query parameter:

response = requests.get("https://api-server.dataquest.io/economic_data/countries")

# Some APIs return JSON as a string that needs extra parsing
data = json.loads(response.json())
print(f"Total countries: {len(data)}")
print(f"First country: {data[0]['short_name']}")
Total countries: 100
First country: Aruba

This gets the first 100 countries from the database.

Many APIs have a default limit on how many results they return. Ours is set to 100. This is a common pattern. It keeps responses manageable and stops your app from getting too much data at once.

A Note About JSON Parsing

You might wonder why we use both response.json() and json.loads(). Here's what's happening.

Some APIs (like this one) return data as a JSON-encoded string. Not direct JSON objects. So we need two steps:

  1. response.json() turns the HTTP response body into a Python string
  2. json.loads() parses that JSON string into actual Python objects (lists and dictionaries)

Most APIs only need response.json(). But if you ever get errors working with your data, try this double-parsing trick.

Adding a Query Parameter: Two Approaches

Now let's filter this data. We'll use a query parameter to show only countries in Sub-Saharan Africa. We can do this in two ways:

Method 1: Adding parameters directly to the URL (what you might copy from API docs):

response = requests.get("https://api-server.dataquest.io/economic_data/countries?filter_by=region=Sub-Saharan%20Africa")
data = json.loads(response.json())
print(f"Filtered countries: {len(data)}")
print(f"First country: {data[0]['short_name']}")
Filtered countries: 48
First country: Angola

Notice the URL includes ?filter_by=region=Sub-Saharan%20Africa. The %20 represents a space because spaces can't be used directly in URLs.

While this works, it's messy. It forces us to have to handle URL encoding ourselves.

Method 2: Using a params dictionary (the recommended way):

params = {
    'filter_by': 'region=Sub-Saharan Africa'
}

response = requests.get(
    "https://api-server.dataquest.io/economic_data/countries",
    params=params
)
data = json.loads(response.json())
print(f"Filtered countries: {len(data)}")
print(f"First country: {data[0]['short_name']}")
Filtered countries: 48
First country: Angola

Both methods give identical results. But the params dictionary approach is cleaner.

The requests library handles URL encoding automatically. You can write "Sub-Saharan Africa" with a regular space. No need to worry about %20.

Working with Multiple Query Parameters

The params dictionary approach really shines when you need multiple query parameters.

Let's say we want just the first 5 countries from Sub-Saharan Africa. Not all 48:

params = {
    'filter_by': 'region=Sub-Saharan Africa',
    'limit': 5
}

response = requests.get(
    "https://api-server.dataquest.io/economic_data/countries",
    params=params
)
data = json.loads(response.json())
print(f"Limited results: {len(data)}")
print(f"First country: {data[0]['short_name']}")
Limited results: 5
First country: Angola

Perfect! We filtered by region and limited results to just 5 countries.

The limit parameter is especially useful with large datasets. You don't want thousands of records overwhelming your app all at once.

This approach is much cleaner than building a URL manually. Like ...?filter_by=region=Sub-Saharan%20Africa&limit=5.

The requests library handles all the encoding and formatting. Your code is easier to read and less likely to have errors.

Common Uses for Query Parameters

A query parameter can serve many purposes when we're working with APIs:

  • Filtering data: Get only records that match specific criteria
  • Sorting results: Order the returned data by a specific field
  • Pagination: Limit the number of results per request with large datasets
  • Searching: Query a dataset for specific terms or values
  • Formatting responses: Say what format or structure you want the returned data in

Sending Data with POST Requests

So far, we've been getting data using GET requests. But what happens when you need to send data to an API?

Maybe you want to create a new blog post. Submit a comment. Add a user to a database. That's where POST requests come in.

When to Use POST Requests

You'll use POST requests when you need to:

  • Create new records (like adding a blog post or registering a user)
  • Submit form data
  • Upload files or images
  • Trigger API actions that change data on the server

The key difference is simple. GET requests only ask for data. POST requests send information in the request body. This lets you send larger amounts of data securely.

Making a POST Request in Python

Let's work through a real example using JSONPlaceholder. It's a free testing API that's perfect for learning.

We'll create a new blog post by sending data to their API:

# JSONPlaceholder is a free API for testing
url = "https://jsonplaceholder.typicode.com/posts"

# The data we want to send
new_post = {
    'title': 'Learning Python APIs',
    'body': 'POST requests let you send data to APIs',
    'userId': 1
}

# Send the POST request
response = requests.post(url, json=new_post)

# Check if it worked
if response.status_code == 201:
    print("Post created successfully!")
    print(response.json())
else:
    print(f"Something went wrong: {response.status_code}")

Try running this code yourself!

When you use requests.post(), the json=new_post parameter does something useful. It turns your Python dictionary into JSON format automatically. Then it sends it in the request body.

A status code of 201 means the API created your new resource successfully.

The API will respond with something like:

{
  'title': 'Learning Python APIs',
  'body': 'POST requests let you send data to APIs',
  'userId': 1,
  'id': 101
}

Notice the API assigned an id to our new post. That's typical behavior when creating new things.

Sending Different Data Types

POST requests can send data in different formats. It depends on what the API expects.

Here are the most common approaches:

JSON data (most common for modern APIs):

response = requests.post(url, json=data_dict)

Form data (similar to HTML forms):

response = requests.post(url, data=data_dict)

With custom headers (for authentication or content type):

headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-api-key'
}
response = requests.post(url, json=data_dict, headers=headers)

Combining POST Requests with Query Parameters

You can use query parameters alongside POST requests. This is handy when you need to both send data and customize how the API processes it:

params = {'version': 'v2'}
response = requests.post(url, json=new_post, params=params)

This makes POST requests incredibly powerful. You can build interactive apps that need to both send and receive data.

Error Handling and Best Practices for Python APIs

Here's the truth about working with APIs. Things go wrong.

Network hiccups. Server timeouts. Rate limits. You name it.

The difference between a fragile script and a production-ready app often comes down to how well you handle these bumps.

Using Try-Except Blocks for API Calls

The foundation of good error handling is wrapping your API requests in try-except blocks.

Let's look at a real example using the ISS location API:

try:
    response = requests.get("http://api.open-notify.org/iss-now.json", timeout=5)
    response.raise_for_status()  # Raises an exception for 4xx or 5xx status codes
    data = response.json()
    print(f"ISS Location: {data}")
except requests.exceptions.Timeout:
    print("The request timed out. The server took too long to respond.")
except requests.exceptions.HTTPError as e:
    print(f"HTTP error occurred: {e}")
except requests.exceptions.RequestException as e:
    print(f"Something went wrong: {e}")

This pattern catches three common problems:

  1. Timeouts: when the server doesn't respond fast enough
  2. HTTP errors: like 404 or 500 status codes
  3. General request issues: like network connectivity problems

The timeout=5 parameter means Python will wait up to 5 seconds before giving up.

Handling Timeout Errors

Timeout errors happen when an API takes too long to respond. Maybe the server is overwhelmed. Or your internet connection is slow.

Either way, you don't want your program to wait forever. Here's how to handle it well:

try:
    response = requests.get(
        "http://api.open-notify.org/iss-now.json",
        timeout=10  # Wait up to 10 seconds
    )
    data = response.json()
    print(f"Current ISS position: {data['iss_position']}")
except requests.exceptions.Timeout:
    print("The ISS tracking API isn't responding. Try again in a moment.")
    # You could implement retry logic here

Setting timeouts between 5 and 30 seconds usually works well. It depends on how fast you expect the API to respond.

For quick data lookups, stick with shorter timeouts. For APIs that process complex requests, give them more time.

Managing Rate Limits

Most APIs have rate limits. They prevent abuse and keep things fair for everyone.

For example, an API might let you make 100 requests per hour. Go over that limit and you'll get a 429 status code. That basically means "slow down."

Here's a practical way to handle rate limits using JSONPlaceholder:

import time

def fetch_posts_safely(max_retries=3):
    url = "https://jsonplaceholder.typicode.com/posts/1"

    for attempt in range(max_retries):
        try:
            response = requests.get(url)

            if response.status_code == 429:
                # Rate limit hit
                wait_time = int(response.headers.get('Retry-After', 60))
                print(f"Rate limit reached. Waiting {wait_time} seconds...")
                time.sleep(wait_time)
                continue

            response.raise_for_status()
            return response.json()

        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                # Last attempt failed, give up
                print(f"All retry attempts failed: {e}")
                return None
            # Wait before trying again (exponential backoff)
            wait_time = 2 ** attempt
            print(f"Request failed. Retrying in {wait_time} seconds...")
            time.sleep(wait_time)

    return None

# Use the function
post_data = fetch_posts_safely()
if post_data:
    print(f"Successfully retrieved: {post_data['title']}")

This approach uses two smart strategies.

First, it has retry logic. It automatically tries again if something fails.

Second, it uses exponential backoff. It waits longer between each retry. 2 seconds, then 4, then 8. This gives overloaded servers time to recover.

Best Practices for Working with APIs

Here are some guidelines that'll save you headaches:

  • Always check status codes: Don't assume requests work. Check the status code before processing the response.
  • Use timeouts: Set reasonable timeouts. This stops your app from hanging forever.
  • Handle JSON parsing carefully: Not all responses contain valid JSON. Even with a 200 status code. Wrap response.json() in a tryexcept block if you're unsure.
  • Respect rate limits: Check API documentation for rate limits. Add appropriate delays between requests.
  • Secure your API keys: Never put API keys directly in your Python code. Use environment variables or config files instead.
  • Log errors for debugging: Keep track of API failures. This helps you spot patterns and fix issues.

Following these practices turns fragile scripts into reliable, production-ready code. Code that handles the messy reality of working with external services.

Wrapping Up: Using an API in Python

APIs give you an efficient way to access real-time data.

From tracking the ISS's location to building machine learning models. By making API requests and working with JSON data, you can add dynamic features to your data science and AI apps.

Throughout this tutorial, we've covered the essential skills for working with APIs in Python.

You've learned how to make GET requests to get data. How to use query parameters to filter results. How to send data with POST requests. And how to add proper error handling for production-ready code.

These foundational API skills open up countless possibilities for your Python projects.

For example, you could use real-time ISS pass time data to train a machine learning model. One that predicts future pass times for any location.

Building such a Python project might involve setting up a data pipeline. One that regularly fetches API data, preps it, and feeds it into the model.

Knowing how to interact with APIs in Python is a fundamental skill. Especially for data science and AI work.

APIs let you connect multiple data sources smoothly. This significantly expands what you can achieve with Python.

Next Steps to Expand Your Python API Skills

Explore our interactive APIs and Web Scraping course. It's perfect for sharpening your API skills.

If you're just starting, our Introduction to Python Programming course is a great place to begin.

For those focused on AI, check out our Generative AI Fundamentals in Python skill path. It explores cutting-edge techniques.

Charlie Custer

About the author

Charlie Custer

Charlie is a student of data science, and also a content marketer at Dataquest. In his free time, he's learning to mountain bike and making videos about it.