Request & Response Objects
The request object is Flask's window into the incoming HTTP request — query parameters, form data, headers, and JSON — while the response is whatever your view returns to the browser.
Learn Request & Response Objects in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll read data the client sends, branch on the HTTP method, and craft responses with custom status codes, headers, and JSON.
The request object is a special global that Flask populates for each incoming request. You import it once and read from it inside any view function.
Two of its most useful attributes are request.args (query-string values from the URL) and request.form (data submitted in a POST body). Both behave like dictionaries, and .get() lets you supply a default when a key is missing.
The example below reads a name query parameter — for a URL like /greet?name=Ada it returns a personalized greeting. If no name is supplied, it falls back to "stranger".
Run this and the test client prints Hello, Ada! for the first request and Hello, stranger! for the second, proving the default kicks in when name is absent.
A single route can respond to multiple HTTP methods. List them in the decorator with methods=["GET", "POST"] , then check request.method inside the view to decide what to do.
The example below shows a form on a GET request and reads the submitted value from request.form on a POST. The POST branch returns a confirmation message built from the data the user typed.
By default a view returns a string with status 200 OK . To control the status code, return a tuple of (body, status) . To set headers too, return (body, status, headers) or build a response with make_response(...) .
For APIs, jsonify(...) serializes a dictionary to JSON and sets the right Content-Type . The example below returns JSON with an explicit 201 Created status and a custom header.
Complete the route below. Replace each ___ so it accepts GET and POST, reads the posted email , and returns JSON.
Your route only allows GET. Add the method to the decorator: methods=["GET", "POST"] . By default a route accepts GET only.
Indexing a missing key raises an error and returns 400. Prefer request.form.get("name") , which returns None (or your default) instead of crashing.
Build a route that echoes back a query parameter as JSON.
Lesson 7 complete — you control both sides of the conversation!
You can now read query strings and form data from request , branch on request.method , and return responses with custom status codes, headers, and JSON.
🚀 Up next: Handling Forms — collect, validate, and process user input cleanly and safely.
Practice quiz
Where do query-string values (after the ?) appear?
- request.form
- request.json
- request.args
- request.cookies
Answer: request.args. request.args holds URL query-string parameters.
Where does data submitted in a POST form body appear?
- request.args
- request.path
- request.headers
- request.form
Answer: request.form. request.form holds data posted in an HTML form body.
Which attribute tells you the HTTP method of the request?
- request.method
- request.verb
- request.type
- request.action
Answer: request.method. request.method holds the method string like "GET" or "POST".
How do you return a body with a custom status code?
- return body.status(404)
- return (body, status) tuple
- set request.status
- return status(body)
Answer: return (body, status) tuple. Returning a (body, status) tuple sets the HTTP status code.
Which helper serializes a dict to a JSON response with the right Content-Type?
- str(data)
- json.dumps(data)
- jsonify(data)
- render_json(data)
Answer: jsonify(data). jsonify(...) serializes to JSON and sets application/json.
Which function builds a Response object you can then modify?
- new_response()
- build_response()
- Response.create()
- make_response(...)
Answer: make_response(...). make_response(...) returns a Response whose status_code and headers you can set.
Why prefer request.form.get("x") over request.form["x"]?
- It returns None/default instead of a 400 when missing
- It is faster
- It validates the value
- It sends JSON
Answer: It returns None/default instead of a 400 when missing. .get() avoids a 400 Bad Request when the key is absent.
By default, what status code does a view returning a plain string send?
- 201 Created
- 200 OK
- 302 Found
- 204 No Content
Answer: 200 OK. A plain string response defaults to 200 OK.
What status results from POSTing to a route that only allows GET?
- 404 Not Found
- 500 Internal Error
- 405 Method Not Allowed
- 403 Forbidden
Answer: 405 Method Not Allowed. 405 Method Not Allowed means the verb isn't permitted on that route.
How do you let one route accept both GET and POST?
- @app.both_methods
- @app.post and @app.get only
- request.allow("POST")
List the allowed methods in the @app.route decorator's methods argument.