Of course! In Flask, the return statement is the primary way your application sends a response back to the client (usually a web browser). This response typically consists of three key parts:

- The Status Code: A number indicating the result of the request (e.g.,
200for OK,404for Not Found,500for Internal Server Error). - The Response Body: The actual content the user sees, like HTML, JSON, or plain text.
- The Headers: Additional information sent with the response (e.g.,
Content-Type,Content-Length,Cache-Control).
Let's break down the different ways to use return in Flask, from the simplest to the most powerful.
The Simplest Case: Returning a String
This is the most basic way to return a response. Flask automatically creates a 200 OK response and sets the Content-Type header to text/html.
Example:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return '<h1>Hello, World!</h1>'
if __name__ == '__main__':
app.run(debug=True)
What happens:

- Status Code:
200 OK(default) - Body:
<h1>Hello, World!</h1> - Headers:
Content-Type: text/html; charset=utf-8(default)
Returning a Tuple (The Traditional Way)
Before more advanced features, Flask allowed you to return a tuple with up to three elements: (response, status, headers).
- Element 1: The response string (or bytes).
- Element 2 (optional): The status code.
- Element 3 (optional): A dictionary or list of headers.
Example:
from flask import Flask
app = Flask(__name__)
@app.route('/old-style')
def old_style():
# Return a tuple: (response, status_code, headers)
response_tuple = (
"This is a custom message.",
202, # Status Code: 202 Accepted
{'X-Custom-Header': 'MyValue'} # Custom Headers
)
return response_tuple
if __name__ == '__main__':
app.run(debug=True)
What happens:
- Status Code:
202 Accepted - Body:
This is a custom message. - Headers:
X-Custom-Header: MyValueand the defaultContent-Type.
Returning a Response Object (The Modern & Recommended Way)
The best practice is to use the make_response() function. This gives you full control over the response object before you return it. You can modify the status code, headers, and even the body after creating it.

Why is this better?
- Readability: The code is clearer. You set the response and then return it.
- Flexibility: You can easily modify the response. For example, you can add a cookie or change the headers.
- Consistency: This is the standard, idiomatic way to handle complex responses in modern Flask.
Example:
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/modern-style')
def modern_style():
# Create the initial response
response = make_response('<h2>This is a modern response.</h2>')
# Modify the response
response.status_code = 201 # Status Code: 201 Created
response.headers['X-Another-Header'] = 'AnotherValue'
response.set_cookie('my_cookie', 'cookie_value')
return response
if __name__ == '__main__':
app.run(debug=True)
What happens:
- Status Code:
201 Created - Body:
<h2>This is a modern response.</h2> - Headers:
X-Another-Header: AnotherValue,Set-Cookie: my_cookie=cookie_value, andContent-Type.
Returning JSON Data (Very Common for APIs)
When building a web API, you almost always want to return data in JSON format. The jsonify() helper function is perfect for this. It does two important things:
- Serializes your Python dictionary/list into a JSON string.
- Sets the
Content-Typeheader toapplication/json, which tells the client how to parse the response.
Example:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api/user/<int:user_id>')
def get_user(user_id):
# In a real app, you would fetch this from a database
user_data = {
'id': user_id,
'name': 'John Doe',
'email': 'john.doe@example.com'
}
# jsonify converts the dict to a JSON string and sets the Content-Type header
return jsonify(user_data)
if __name__ == '__main__':
app.run(debug=True)
What happens:
- Status Code:
200 OK(default) - Body:
{"email": "john.doe@example.com", "id": 123, "name": "John Doe"} - Headers:
Content-Type: application/json
You can also set the status code and headers with jsonify:
@app.route('/api/not-found')
def not_found():
response = jsonify({'error': 'User not found'})
response.status_code = 404
return response
Redirecting the User
To redirect a user to another URL, you use the redirect() function. This sends a 302 Found status code by default, which tells the browser to make a new GET request to the new URL.
Example:
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/login')
def login():
# Redirect to the 'home' page
return redirect(url_for('home'))
@app.route('/')
def home():
return 'Welcome to the Home Page!'
if __name__ == '__main__':
app.run(debug=True)
If you navigate to /login, you will be automatically sent to .
You can also specify the redirect code:
@app.route('/moved-permanently')
def moved_permanently():
# 301 Moved Permanently
return redirect(url_for('home'), code=301)
Summary Table
| Method | Use Case | Status Code (Default) | Content-Type (Default) |
Example |
|---|---|---|---|---|
return "string" |
Simple HTML/text responses. | 200 OK |
text/html |
return "Hello" |
return (tuple, ...) |
Quick, simple custom responses. | 200 OK (or specified) |
text/html (or specified) |
return ("Hi", 201) |
make_response() |
Recommended. For full control over the response object. | 200 OK (or specified) |
text/html (or specified) |
resp = make_response("...") |
jsonify() |
For APIs. Returns JSON data. | 200 OK |
application/json |
jsonify({'key': 'val'}) |
redirect() |
Redirecting to another URL/route. | 302 Found |
text/html |
redirect(url_for('home')) |
Key Takeaways
- For simple HTML, just
return "..."is fine. - For APIs, always use
jsonify()to return JSON data. - For any response that needs custom status codes, headers, or cookies, use
make_response(). This is the most flexible and recommended approach for building robust applications.
