Python GET Requests
Table of Contents + β
In the last lesson you set up the requests Library and saw how it lets your Python code talk to the internet. Now we put it to work. The most common thing you will ever do with an API is ask it for some data. That is what a GET request is for.
π€ Why GET Requests?
Say you are building a small app. You need a list of users. Or some posts. Or the current weather. That data lives on someone elseβs server, not on your machine. So how do you get it into your program?
You ask for it. A GET request is your program saying to a server: βplease send me this data.β The server reads what you asked for and sends it back.
There is one key thing to remember. GET only reads. It never changes anything on the server. You can run the same GET request a hundred times and the server stays exactly the same. Think of it like reading a page on Wikipedia. You can open it again and again. Just looking at it does not edit the page.
π§© What a GET Request Looks Like
A test API is a free server made for practice. It gives you fake but realistic data so you can learn without breaking anything real. We will use JSONPlaceholder, a popular free one.
First make sure requests is installed. It is a third-party library, so it does not come with Python by default. Run this in your terminal:
pip install requestsHere is the simplest GET request you can write. It asks JSONPlaceholder for a single post.
import requests
response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
print(response.status_code)print(response.text)Let me walk through it line by line:
import requestsbrings in the library so we can use it.requests.get(...)sends the GET request to that web address and waits for the reply. The reply is stored in a variable we calledresponse.response.status_codeis a number the server sends back to say how it went. A status code of200means success.response.textis the raw reply as plain text.
This is the kind of thing it prints. The data comes from the internet, so this is example output. Yours may look slightly different.
Output
200{ "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}That 200 tells us the request worked. The block after it is the post the server sent back.
π¦ Reading JSON with response.json()
The reply above looks like a Python dictionary, but it is not yet. As response.text it is just a long string of characters. You cannot pull a value out of a string by key.
JSON is the common text format APIs use to send data. It looks almost exactly like Python dictionaries and lists. The requests library can turn that JSON text into real Python objects for you with one method: response.json().
Here we fetch the same post and read it as proper Python data:
import requests
response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
post = response.json()
print(type(post))print(post["title"])print(post["userId"])What is happening here:
response.json()reads the JSON reply and gives you back a real Pythondict.- We store that dict in
post. - Now we can grab values by key, just like any dictionary. So
post["title"]works.
This is the example output:
Output
<class 'dict'>sunt aut facere repellat provident occaecati excepturi optio reprehenderit1See the difference? type(post) shows dict, not str. That means we can now use normal dictionary tools on the data.
Tip
Use response.text when you want the raw reply, and response.json() when the API sends JSON and you want to work with the values. For almost every API, you want response.json().
π Sending Query Parameters with params
Often you do not want everything. You want a filtered slice. Like βonly the posts written by user number 1.β You tell the server what you want by adding query parameters to the request.
Query parameters are little key-and-value pairs that get attached to the end of the web address after a ?. You could type them by hand into the address, but that gets messy and easy to break. The clean way is to pass a dictionary to params.
Here we ask only for the posts that belong to user 1:
import requests
response = requests.get( "https://jsonplaceholder.typicode.com/posts", params={"userId": 1})
print(response.url)
posts = response.json()print(len(posts))The important parts:
params={"userId": 1}is the filter.requeststakes that dictionary and builds the full address for you.response.urlshows the final address that was actually requested, so you can see whatparamsdid.postsis now a list of dictionaries, one dictionary per post.len(posts)counts how many posts came back.
This is the example output:
Output
https://jsonplaceholder.typicode.com/posts?userId=110Notice how requests glued ?userId=1 onto the address for you. You wrote a clean dictionary and let the library handle the formatting. That is much safer than building the string yourself.
Note
When the API returns one item (like /posts/1), response.json() gives you a dict. When it returns many items (like /posts), it gives you a list of dicts. Check which one you have before you use it.
π Looping Over the Results
Once you have a list back, you almost always want to go through it item by item. A normal for loop does the job, since the result is just a regular Python list.
Here we fetch user 1βs posts and print the title of each one:
import requests
response = requests.get( "https://jsonplaceholder.typicode.com/posts", params={"userId": 1})
posts = response.json()
for post in posts: print(f"Post {post['id']}: {post['title']}")Reading the loop:
postsis the list of post dictionaries we got back.- The
forloop hands us onepostdictionary at a time. - Inside,
post['id']andpost['title']pull values out of that single post.
This is the example output, trimmed to the first few lines:
Output
Post 1: sunt aut facere repellat provident occaecati excepturi optio reprehenderitPost 2: qui est essePost 3: ea molestias quasi exercitationem repellat qui ipsa sit autPost 4: eum et est occaecatiPost 5: nesciunt quas odioThat is the full pattern most API code follows. Send a GET. Read the JSON. Loop the results. Once this clicks, a lot of real-world Python opens up to you.
β οΈ Common Mistakes
A few things trip people up early on:
- Forgetting to call
.json()and trying to index the raw text. You cannot doresponse["title"]on a string.
# β Avoid: response is a Response object, not the datatitle = response["title"]
# β
Good: turn it into Python data firstdata = response.json()title = data["title"]- Building the query string by hand instead of using
params. It is easy to forget a?or an&, or to leave a space in.
# β Avoid: messy and easy to breakresponse = requests.get("https://jsonplaceholder.typicode.com/posts?userId=1")
# β
Good: let requests build it safelyresponse = requests.get( "https://jsonplaceholder.typicode.com/posts", params={"userId": 1})- Assuming you always get a list. A request for one item gives a single dict, so looping over it loops over its keys, not what you expect.
- Ignoring the status code. If the request failed,
response.json()may not contain the data you assume. Checkresponse.status_codefirst when something looks off.
β Best Practices
Small habits that keep your API code clean:
- Use
params={...}for query parameters instead of typing them into the address yourself. - Reach for
response.json()whenever the API returns JSON, then treat the result as a normal dict or list. - Check
response.status_code(or printresponse.url) while you are still figuring out a new API. - Remember that GET only reads. If you ever want to send or change data on the server, that is a different kind of request, not GET.
π§© What Youβve Learned
β A GET request asks a server for data and only reads. It never changes anything on the server.
β
requests.get(url) sends the request and gives you back a Response object.
β
response.json() turns the JSON reply into real Python dicts and lists you can use.
β
params={...} adds query parameters so you can ask for a filtered slice of the data.
β
When the result is a list, a plain for loop lets you go through each item.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does a GET request do on the server?
Why: GET is read-only. Running the same GET request again does not change anything on the server.
- 2
Why use response.json() instead of response.text?
Why: response.text is a plain string, while response.json() parses the JSON into Python objects so you can access values by key.
- 3
What is the cleanest way to send query parameters with requests?
Why: Passing params={...} lets requests build the query string safely instead of you formatting it by hand.
- 4
When an API endpoint like /posts returns many items, what does response.json() usually give you?
Why: Endpoints that return many items give back a list of dicts, so a normal for loop works over them.
π Whatβs Next?
You can now read data from any API. The next step is sending data the other way, creating something new on the server.