2025, Dec 17 09:00

How to Fix Flask 405 Method Not Allowed for POST Requests by Declaring methods=['POST'] on the Route

Getting a Flask 405 Method Not Allowed on a POST route? Learn why Flask defaults to GET and fix form submissions by declaring methods=['POST'] to accept POST.

Getting a 405 Method Not Allowed on a seemingly straightforward Flask route is annoying, especially when the form clearly sends a POST and the endpoint looks correct. The root cause here is subtle but simple: Flask defaults to handling GET unless told otherwise.

Minimal example that triggers the 405

svc = Flask(__name__)
@svc.route('/')
def home():
    return render_template('index.html')
@svc.route('/submit')
def handle_submit():
    user_name = request.form.get('username')
    return f'Hello, {user_name}!'
if __name__ == '__main__':
    svc.run()

Submitting a POST to /submit results in 405 Method Not Allowed.

What’s actually happening

In Flask, a route without an explicit methods parameter only accepts GET. When a form uses method="post" and hits /submit, Flask looks for a POST handler on that path, doesn’t find one, and responds with 405. The route exists, but it’s not registered for the HTTP verb you’re using.

How to fix the route to accept POST

Declare the allowed HTTP methods on the route decorator. Here, we need POST.

svc = Flask(__name__)
@svc.route('/')
def home():
    return render_template('index.html')
@svc.route('/submit', methods=['POST'])
def handle_submit():
    user_name = request.form.get('username')
    return f'Hello, {user_name}!'
if __name__ == '__main__':
    svc.run()

Why this detail matters

HTTP verb handling is explicit in Flask. Relying on defaults can lead to confusing behavior when forms or clients switch methods. Declaring methods on routes makes intent clear, avoids 405 errors, and prevents accidental exposure of endpoints to verbs you didn’t plan to support.

Final thoughts

When wiring up form submissions or API endpoints in Flask, always declare the methods you expect. If the endpoint only handles form posts, use methods=['POST']. That small addition saves time, clarifies your API surface, and aligns the route behavior with how the client actually calls it.