Flask
Web Development
Data Extraction
Python
HTTP Requests

Get the data received in a Flask request

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In Flask, incoming request data can come from several places: query parameters, HTML forms, JSON bodies, files, and headers. The correct way to read it depends on the content type and HTTP method, so a reliable Flask handler starts by understanding what kind of request the client is actually sending.

Read Query Parameters, Form Data, and JSON Separately

Flask exposes request data through the request object. Different containers correspond to different parts of the HTTP request.

python
1from flask import Flask, request, jsonify
2
3app = Flask(__name__)
4
5@app.route('/search')
6def search():
7    query = request.args.get('q', '')
8    limit = request.args.get('limit', default=10, type=int)
9    return jsonify(query=query, limit=limit)

request.args is for query-string values such as /search?q=flask&limit=5.

For HTML form posts, use request.form.

python
1@app.route('/submit', methods=['POST'])
2def submit_form():
3    username = request.form.get('username', '')
4    email = request.form.get('email', '')
5    return jsonify(username=username, email=email)

For JSON APIs, use request.get_json().

python
1@app.route('/api/items', methods=['POST'])
2def create_item():
3    payload = request.get_json(silent=False)
4    name = payload.get('name')
5    quantity = payload.get('quantity', 0)
6    return jsonify(name=name, quantity=quantity), 201

This separation matters because a JSON request will not populate request.form, and a normal form post will not automatically become JSON.

Access Raw Body, Files, and Headers When Needed

Sometimes you need lower-level access to the request body. Flask provides that too.

python
1@app.route('/raw', methods=['POST'])
2def raw_body():
3    body = request.get_data(as_text=True)
4    return jsonify(length=len(body))

File uploads are available through request.files.

python
1@app.route('/upload', methods=['POST'])
2def upload_file():
3    uploaded = request.files.get('file')
4    if uploaded is None or uploaded.filename == '':
5        return jsonify(error='missing file'), 400
6
7    uploaded.save(f'/tmp/{uploaded.filename}')
8    return jsonify(saved=uploaded.filename)

Headers live in request.headers.

python
1@app.route('/headers')
2def headers():
3    user_agent = request.headers.get('User-Agent', 'unknown')
4    request_id = request.headers.get('X-Request-Id')
5    return jsonify(user_agent=user_agent, request_id=request_id)

Each of these access paths exists for a different reason. Treating them as interchangeable usually leads to bugs.

Validate Data Instead of Trusting It

Reading request data is only the first step. You still need to validate required fields, types, and allowed ranges.

python
1@app.route('/api/register', methods=['POST'])
2def register():
3    payload = request.get_json() or {}
4    username = payload.get('username', '').strip()
5    age = payload.get('age')
6
7    if not username:
8        return jsonify(error='username is required'), 400
9    if not isinstance(age, int) or age < 13:
10        return jsonify(error='invalid age'), 400
11
12    return jsonify(username=username, age=age), 201

This keeps parsing separate from business rules, which makes the route easier to reason about and test.

Match the Access Method to the Client

Many request-handling bugs happen when the server expects one format and the client sends another. For example, JavaScript fetch with Content-Type: application/json should be read as JSON, while a browser form submitted with application/x-www-form-urlencoded should be read from request.form.

When debugging, inspect the request method, Content-Type, and actual payload rather than guessing.

Flask also provides request.values, which merges query parameters and form fields. That convenience can be useful for quick prototypes, but it can also hide where a value really came from. In production handlers, reading from the explicit source is usually clearer and safer.

Common Pitfalls

Reading request.form when the client actually sent JSON is a common source of mysteriously empty values.

Using request.json or get_json() without checking the request content type can produce confusing errors when clients send the wrong payload format.

Accessing required fields with direct dictionary-style indexing can raise exceptions for missing keys. Use .get() and validate intentionally.

Summary

  • Use request.args for query parameters, request.form for form posts, and request.get_json() for JSON bodies.
  • Use request.files for uploads and request.headers for header values.
  • Read the data first, then validate it explicitly.
  • Always match your Flask access method to the payload format the client is actually sending.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.