My understanding is that request.args in Flask contains the URL encoded parameters from a GET request while request.form contains POST data. What I’m having a hard time grasping is why when sending a POST request, trying to access the data with request.form returns a 400 error but when I try to access it with request.args it seems to work fine.

I have tried sending the request with both Postman and curl and the results are identical.

curl -X POST -d {"name":"Joe"} http://127.0.0.1:8080/testpoint --header "Content-Type:application/json"

Code:

@app.route('/testpoint', methods = ['POST'])
def testpoint():
    name = request.args.get('name', '')
    return jsonify(name = name)

You are POST-ing JSON, neither request.args nor request.form will work.

request.form works only if you POST data with the right content types; form data is either POSTed with the application/x-www-form-urlencoded or multipart/form-data encodings.

When you use application/json, you are no longer POSTing form data. Use request.get_json() to access JSON POST data instead:

@app.route('/testpoint', methods = ['POST'])
def testpoint():
    name = request.get_json().get('name', '')
    return jsonify(name = name)

As you state, request.args only ever contains values included in the request query string, the optional part of a URL after the ? question mark. Since it’s part of the URL, it is independent from the POST request body.

Your json data in curl is wrong, so Flask does not parse data to form.

Send data like this: '{"name":"Joe"}'

curl -X POST -d '{"name":"Joe"}' http://example.com:8080/testpoint --header "Content-Type:application/json"