Get the data received in a Flask request
Question:
I want to be able to get the data sent to my Flask app. I’ve tried accessing request.data
but it is an empty string. How do you access request data?
from flask import request
@app.route('/', methods=['GET', 'POST'])
def parse_request():
data = request.data # data is empty
# need posted data here
The answer to this question led me to ask Get raw POST body in Python Flask regardless of Content-Type header next, which is about getting the raw data rather than the parsed data.
Answers:
To get the raw data, use request.data
. This only works if it couldn’t be parsed as form data, otherwise it will be empty and request.form
will have the parsed data.
from flask import request
request.data
The docs describe the attributes available on the request
object (from flask import request
) during a request. In most common cases request.data
will be empty because it’s used as a fallback:
request.data
Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
request.args
: the key/value pairs in the URL query string
request.form
: the key/value pairs in the body, from a HTML post form, or JavaScript request that isn’t JSON encoded
request.files
: the files in the body, which Flask keeps separate from form
. HTML forms must use enctype=multipart/form-data
or files will not be uploaded.
request.values
: combined args
and form
, preferring args
if keys overlap
request.json
: parsed JSON data. The request must have the application/json
content type, or use request.get_json(force=True)
to ignore the content type.
All of these are MultiDict
instances (except for json
). You can access values using:
request.form['name']
: use indexing if you know the key exists
request.form.get('name')
: use get
if the key might not exist
request.form.getlist('name')
: use getlist
if the key is sent multiple times and you want a list of values. get
only returns the first value.
For URL query parameters, use request.args
.
search = request.args.get("search")
page = request.args.get("page")
For posted form input, use request.form
.
email = request.form.get('email')
password = request.form.get('password')
For JSON posted with content type application/json
, use request.get_json()
.
data = request.get_json()
If you post JSON with content type application/json
, use request.get_json()
to get it in Flask. If the content type is not correct, None
is returned. If the data is not JSON, an error is raised.
@app.route("/something", methods=["POST"])
def do_something():
data = request.get_json()
To get the raw post body regardless of the content type, use request.get_data()
. If you use request.data
, it calls request.get_data(parse_form_data=True)
, which will populate the request.form
MultiDict
and leave data
empty.
The raw data is passed in to the Flask application from the WSGI server as request.stream
. The length of the stream is in the Content-Length
header.
length = request.headers["Content-Length"]
data = request.stream.read(length)
It is usually safer to use request.get_data()
instead.
Here’s an example of parsing posted JSON data and echoing it back.
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/foo', methods=['POST'])
def foo():
data = request.json
return jsonify(data)
To post JSON with curl:
curl -i -H "Content-Type: application/json" -X POST -d '{"userId":"1", "username": "fizz bizz"}' http://localhost:5000/foo
Or to use Postman:
To parse JSON, use request.get_json()
.
@app.route("/something", methods=["POST"])
def do_something():
result = handle(request.get_json())
return jsonify(data=result)
To get JSON posted without the application/json
content type, use request.get_json(force=True)
.
@app.route('/process_data', methods=['POST'])
def process_data():
req_data = request.get_json(force=True)
language = req_data['language']
return 'The language value is: {}'.format(language)
To post JSON with jQuery in JavaScript, use JSON.stringify
to dump the data, and set the content type to application/json
.
var value_data = [1, 2, 3, 4];
$.ajax({
type: 'POST',
url: '/process',
data: JSON.stringify(value_data),
contentType: 'application/json',
success: function (response_data) {
alert("success");
}
});
Parse it in Flask with request.get_json()
.
data = request.get_json()
To get request.form
as a normal dictionary , use request.form.to_dict(flat=False)
.
To return JSON data for an API, pass it to jsonify
.
This example returns form data as JSON data.
@app.route('/form_to_json', methods=['POST'])
def form_to_json():
data = request.form.to_dict(flat=False)
return jsonify(data)
Here’s an example of POST form data with curl, returning as JSON:
$ curl http://127.0.0.1:5000/data -d "name=ivanleoncz&role=Software Developer"
{
"name": "ivanleoncz",
"role": "Software Developer"
}
When posting form data with an HTML form, be sure the input
tags have name
attributes, otherwise they won’t be present in request.form
.
@app.route('/', methods=['GET', 'POST'])
def index():
print(request.form)
return """
<form method="post">
<input type="text">
<input type="text" id="txt2">
<input type="text" name="txt3" id="txt3">
<input type="submit">
</form>
"""
ImmutableMultiDict([('txt3', 'text 3')])
Only the txt3
input had a name
, so it’s the only key present in request.form
.
If the content type is recognized as form data, request.data
will parse that into request.form
and return an empty string.
To get the raw data regardless of content type, call request.get_data()
. request.data
calls get_data(parse_form_data=True)
, while the default is False
if you call it directly.
If the body is recognized as form data, it will be in request.form
. If it’s JSON, it will be in request.get_json()
. Otherwise the raw data will be in request.data
. If you’re not sure how data will be submitted, you can use an or
chain to get the first one with data.
def get_request_data():
return (
request.args
or request.form
or request.get_json(force=True, silent=True)
or request.data
)
request.args
contains args parsed from the query string, regardless of what was in the body, so you would remove that from get_request_data()
if both it and a body should data at the same time.
Use request.get_json()
to get posted JSON data.
data = request.get_json()
name = data.get('name', '')
Use request.form
to get data when submitting a form with the POST method.
name = request.form.get('name', '')
Use request.args
to get data passed in the query string of the URL, like when submitting a form with the GET method.
request.args.get("name", "")
request.form
etc. are dict-like, use the get
method to get a value with a default if it wasn’t passed.
Here’s an example of posting form data to add a user to a database. Check request.method == "POST"
to check if the form was submitted. Use keys from request.form
to get the form data. Render an HTML template with a <form>
otherwise. The fields in the form should have name
attributes that match the keys in request.form
.
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route("/user/add", methods=["GET", "POST"])
def add_user():
if request.method == "POST":
user = User(
username=request.form["username"],
email=request.form["email"],
)
db.session.add(user)
db.session.commit()
return redirect(url_for("index"))
return render_template("add_user.html")
<form method="post">
<label for="username">Username</label>
<input type="text" name="username" id="username">
<label for="email">Email</label>
<input type="email" name="email" id="email">
<input type="submit">
</form>
@app.route('/addData', methods=['POST'])
def add_data():
data_in = mongo.db.Data
id = request.values.get("id")
name = request.values.get("name")
newuser = {'id' : id, 'name' : name}
if voter.find({'id' : id, 'name' : name}).count() > 0:
return "Data Exists"
else:
data_in.insert(newuser)
return "Data Added"
When writing a Slack bot, which is supposed to send JSON data, I got a payload where the Content-Type
was application/x-www-form-urlencoded
.
I tried request.get_json()
and it didn’t work.
@app.route('/process_data', methods=['POST'])
def process_data():
req_data = request.get_json(force=True)
Instead I used request.form
to get the form data field that contained JSON, then loaded that.
from flask import json
@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
req_data = json.loads(request.form["payload"])
request.data
This is great to use but remember that it comes in as a string and will need iterated through.
Import request:
from flask import request
URL query parameters:
name = request.args.get("name")
age = request.args.get("age")
Form Input:
name = request.form.get('name')
age = request.form.get('age')
OR (use indexing if you know the key exists, specify the name of input fields)
name = request.form['name']
age = request.form['age']
JSON Data (for content type application/json)
data = request.get_json()
Try – >
from flask import request
@app.route('/', methods=['GET', 'POST'])
def parse_request():
if request.method == 'POST':
data = request.form.get('data')
You can get request data from
request.form
for form data, this includes form and file data,
request.json
and request.get_json
for JSON data
request.headers
for headers
request.args
to get query params
They’re all like a dictionary, use request.form['name']
if you know the key exists, or request.form.get('name')
if it is optional.
I just faced the same need. I have to save information in case of any unexpected situation. So, I use the following formula:
Info = "%s/%s/%s" % (request.remote_addr, repr(request), repr(session))
repr(request) will give a string representation of the basic information. You could add user-agent data with:
request.headers.get(‘User-Agent’)
I also save the session continent as it could contain valuable information
With all these good answers, is still couldn’t find why it didn’t work for me.
The solution was in debugging.
Though this is not "THE" answer, this is a link to the video that helped me debug my work on vscode, and therefore find the right way to get the data passed from ajax
I want to be able to get the data sent to my Flask app. I’ve tried accessing request.data
but it is an empty string. How do you access request data?
from flask import request
@app.route('/', methods=['GET', 'POST'])
def parse_request():
data = request.data # data is empty
# need posted data here
The answer to this question led me to ask Get raw POST body in Python Flask regardless of Content-Type header next, which is about getting the raw data rather than the parsed data.
To get the raw data, use request.data
. This only works if it couldn’t be parsed as form data, otherwise it will be empty and request.form
will have the parsed data.
from flask import request
request.data
The docs describe the attributes available on the request
object (from flask import request
) during a request. In most common cases request.data
will be empty because it’s used as a fallback:
request.data
Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
request.args
: the key/value pairs in the URL query stringrequest.form
: the key/value pairs in the body, from a HTML post form, or JavaScript request that isn’t JSON encodedrequest.files
: the files in the body, which Flask keeps separate fromform
. HTML forms must useenctype=multipart/form-data
or files will not be uploaded.request.values
: combinedargs
andform
, preferringargs
if keys overlaprequest.json
: parsed JSON data. The request must have theapplication/json
content type, or userequest.get_json(force=True)
to ignore the content type.
All of these are MultiDict
instances (except for json
). You can access values using:
request.form['name']
: use indexing if you know the key existsrequest.form.get('name')
: useget
if the key might not existrequest.form.getlist('name')
: usegetlist
if the key is sent multiple times and you want a list of values.get
only returns the first value.
For URL query parameters, use request.args
.
search = request.args.get("search")
page = request.args.get("page")
For posted form input, use request.form
.
email = request.form.get('email')
password = request.form.get('password')
For JSON posted with content type application/json
, use request.get_json()
.
data = request.get_json()
If you post JSON with content type application/json
, use request.get_json()
to get it in Flask. If the content type is not correct, None
is returned. If the data is not JSON, an error is raised.
@app.route("/something", methods=["POST"])
def do_something():
data = request.get_json()
To get the raw post body regardless of the content type, use request.get_data()
. If you use request.data
, it calls request.get_data(parse_form_data=True)
, which will populate the request.form
MultiDict
and leave data
empty.
The raw data is passed in to the Flask application from the WSGI server as request.stream
. The length of the stream is in the Content-Length
header.
length = request.headers["Content-Length"]
data = request.stream.read(length)
It is usually safer to use request.get_data()
instead.
Here’s an example of parsing posted JSON data and echoing it back.
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/foo', methods=['POST'])
def foo():
data = request.json
return jsonify(data)
To post JSON with curl:
curl -i -H "Content-Type: application/json" -X POST -d '{"userId":"1", "username": "fizz bizz"}' http://localhost:5000/foo
Or to use Postman:
To parse JSON, use request.get_json()
.
@app.route("/something", methods=["POST"])
def do_something():
result = handle(request.get_json())
return jsonify(data=result)
To get JSON posted without the application/json
content type, use request.get_json(force=True)
.
@app.route('/process_data', methods=['POST'])
def process_data():
req_data = request.get_json(force=True)
language = req_data['language']
return 'The language value is: {}'.format(language)
To post JSON with jQuery in JavaScript, use JSON.stringify
to dump the data, and set the content type to application/json
.
var value_data = [1, 2, 3, 4];
$.ajax({
type: 'POST',
url: '/process',
data: JSON.stringify(value_data),
contentType: 'application/json',
success: function (response_data) {
alert("success");
}
});
Parse it in Flask with request.get_json()
.
data = request.get_json()
To get request.form
as a normal dictionary , use request.form.to_dict(flat=False)
.
To return JSON data for an API, pass it to jsonify
.
This example returns form data as JSON data.
@app.route('/form_to_json', methods=['POST'])
def form_to_json():
data = request.form.to_dict(flat=False)
return jsonify(data)
Here’s an example of POST form data with curl, returning as JSON:
$ curl http://127.0.0.1:5000/data -d "name=ivanleoncz&role=Software Developer"
{
"name": "ivanleoncz",
"role": "Software Developer"
}
When posting form data with an HTML form, be sure the input
tags have name
attributes, otherwise they won’t be present in request.form
.
@app.route('/', methods=['GET', 'POST'])
def index():
print(request.form)
return """
<form method="post">
<input type="text">
<input type="text" id="txt2">
<input type="text" name="txt3" id="txt3">
<input type="submit">
</form>
"""
ImmutableMultiDict([('txt3', 'text 3')])
Only the txt3
input had a name
, so it’s the only key present in request.form
.
If the content type is recognized as form data, request.data
will parse that into request.form
and return an empty string.
To get the raw data regardless of content type, call request.get_data()
. request.data
calls get_data(parse_form_data=True)
, while the default is False
if you call it directly.
If the body is recognized as form data, it will be in request.form
. If it’s JSON, it will be in request.get_json()
. Otherwise the raw data will be in request.data
. If you’re not sure how data will be submitted, you can use an or
chain to get the first one with data.
def get_request_data():
return (
request.args
or request.form
or request.get_json(force=True, silent=True)
or request.data
)
request.args
contains args parsed from the query string, regardless of what was in the body, so you would remove that from get_request_data()
if both it and a body should data at the same time.
Use request.get_json()
to get posted JSON data.
data = request.get_json()
name = data.get('name', '')
Use request.form
to get data when submitting a form with the POST method.
name = request.form.get('name', '')
Use request.args
to get data passed in the query string of the URL, like when submitting a form with the GET method.
request.args.get("name", "")
request.form
etc. are dict-like, use the get
method to get a value with a default if it wasn’t passed.
Here’s an example of posting form data to add a user to a database. Check request.method == "POST"
to check if the form was submitted. Use keys from request.form
to get the form data. Render an HTML template with a <form>
otherwise. The fields in the form should have name
attributes that match the keys in request.form
.
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route("/user/add", methods=["GET", "POST"])
def add_user():
if request.method == "POST":
user = User(
username=request.form["username"],
email=request.form["email"],
)
db.session.add(user)
db.session.commit()
return redirect(url_for("index"))
return render_template("add_user.html")
<form method="post">
<label for="username">Username</label>
<input type="text" name="username" id="username">
<label for="email">Email</label>
<input type="email" name="email" id="email">
<input type="submit">
</form>
@app.route('/addData', methods=['POST'])
def add_data():
data_in = mongo.db.Data
id = request.values.get("id")
name = request.values.get("name")
newuser = {'id' : id, 'name' : name}
if voter.find({'id' : id, 'name' : name}).count() > 0:
return "Data Exists"
else:
data_in.insert(newuser)
return "Data Added"
When writing a Slack bot, which is supposed to send JSON data, I got a payload where the Content-Type
was application/x-www-form-urlencoded
.
I tried request.get_json()
and it didn’t work.
@app.route('/process_data', methods=['POST'])
def process_data():
req_data = request.get_json(force=True)
Instead I used request.form
to get the form data field that contained JSON, then loaded that.
from flask import json
@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
req_data = json.loads(request.form["payload"])
request.data
This is great to use but remember that it comes in as a string and will need iterated through.
Import request:
from flask import request
URL query parameters:
name = request.args.get("name")
age = request.args.get("age")
Form Input:
name = request.form.get('name')
age = request.form.get('age')
OR (use indexing if you know the key exists, specify the name of input fields)
name = request.form['name']
age = request.form['age']
JSON Data (for content type application/json)
data = request.get_json()
Try – >
from flask import request
@app.route('/', methods=['GET', 'POST'])
def parse_request():
if request.method == 'POST':
data = request.form.get('data')
You can get request data from
request.form
for form data, this includes form and file data,request.json
andrequest.get_json
for JSON datarequest.headers
for headersrequest.args
to get query params
They’re all like a dictionary, use request.form['name']
if you know the key exists, or request.form.get('name')
if it is optional.
I just faced the same need. I have to save information in case of any unexpected situation. So, I use the following formula:
Info = "%s/%s/%s" % (request.remote_addr, repr(request), repr(session))
repr(request) will give a string representation of the basic information. You could add user-agent data with:
request.headers.get(‘User-Agent’)
I also save the session continent as it could contain valuable information
With all these good answers, is still couldn’t find why it didn’t work for me.
The solution was in debugging.
Though this is not "THE" answer, this is a link to the video that helped me debug my work on vscode, and therefore find the right way to get the data passed from ajax