[python] Get the data received in a Flask request

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.

This question is related to python flask werkzeug

The answer is


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>

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)

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.


@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"

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.


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()

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 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

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.


request.data

This is great to use but remember that it comes in as a string and will need iterated through.


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.


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.


My problem was similar. I got a payload POST request when a user clicked a button from my slackbot. The Content-Type was application/x-www-form-urlencoded. I used Flask, Python3.

I tried this solution and it didn't work

@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)

My solution 1 was:

from urllib.parse import parse_qs
# Some code
@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():    
    # request.get_data() returned a bytestring
    # parse_qs() returned a dict from a bytestring. This dict has 1 pair
    # I tried payload_dict.keys() to see what keys in the dict and it had one key only
    payload_dict = parse_qs(request.get_data())

    # Get the value of the key from payload_dict
    # Value of the key from payload_dict is an array, length = 1
    payload_dict_value_arr = payload_dict[b'payload']

    # Get data from the index[0] of the array payload_dict_value_arr
    data = payload_dict_value_arr[0]   

    # convert a string (representation of a Dict)) to a Dict
    # Note that if you have single quotes as a part of your keys or values this will
    # fail due to improper character replacement.
    # This solution is only recommended if you have a strong aversion 
    # to the eval solution.
    datajson = json.loads(data)

    # get value of key "channel"
    channel = datajson["channel"]
    print(channel) {'id': 'D01ACC2E8S3', 'name': 'directmessage'}

My solution 2, a bit shorter:

@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
   payload = request.form  # return an ImmutableMultiDict with 1 pair

   a1 = payload['payload']  # get value of key 'payload'

   # Note that if you have single quotes as a part of your keys or values this will
   # fail due to improper character replacement.
   # convert a string (representation of a Dict)) to a Dict
   a2 = json.loads(a1)

   # get value of key "channel"
   channel = a2["channel"] 
   print(channel) # {'id': 'D01ACC2E8S3', 'name': 'directmessage'}

flask.Request.get_data , Unicode in Flask


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"
}

To parse JSON, use request.get_json().

@app.route("/something", methods=["POST"])
def do_something():
    result = handle(request.get_json())
    return jsonify(data=result)

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 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:

using postman to post JSON


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()

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to flask

Flask at first run: Do not use the development server in a production environment Flask - Calling python function on button OnClick event python-How to set global variables in Flask? In Flask, What is request.args and how is it used? How to print from Flask @app.route to python console What does "app.run(host='0.0.0.0') " mean in Flask Making an asynchronous task in Flask Flask ImportError: No Module Named Flask can you add HTTPS functionality to a python flask web server? How to get http headers in flask?

Examples related to werkzeug

Get raw POST body in Python Flask regardless of Content-Type header Get the data received in a Flask request Configure Flask dev server to be visible across the network Get IP address of visitors using Flask for Python 104, 'Connection reset by peer' socket error, or When does closing a socket result in a RST rather than FIN?