DEV Community 👩‍💻👨‍💻


Posted on

Flask-WTF ReCaptcha not working

It's just not working

So my website has a contact form. On that form I have a ReCaptcha implemented with flask-wtf ReCaptcha.

When I fill out the ReCaptcha it runs and I get the msg "Sending email to {email address} but then it just redirects and flash's the message that it's sending emails but never actually sends them. It's like it skips the mail.send(msg) line. I've done it with both TESTING=True and TESTING=False. With TESTING=Flase I get the error on the form that says "The response parameter is missing" Where's it missing from? because I went through the validation process.

EDIT: It should be noted that I can remove the ReCaptcha and it works fine.

Here's the 3 files that are in play.

The Route

@bp.route('/', methods=['GET', 'POST'])
def contact():
    form = ContactForm()
    name =
    email =
    message =

    # Test output so I can see what's going on
    print(f'Request method: {request.method}')
    print(f'Validation: {form.validate_on_submit()}')
    print(f'Recaptcha: {form.recaptcha}')
    # End test output

    if form.validate_on_submit():
        msg = Message(
            subject=f"New message from {name}",
            From: <a href="mailto://{email}">{name}</a><br>
            Message: {message}

        print(f'Sending email to {msg.recipients[0]}') # more test output
        mail.send(msg) # Seems to skip this line of code.
        flash('Sending your message...')
        return redirect(url_for('blog_bp.home'))

    return render_template(
        'contact_form/contact_form.jinja2', form=form)
Enter fullscreen mode Exit fullscreen mode

The form

# contact_form.jinja2 
{% extends "layout/layout.html" %}

{% block content %}
<div class="container">
    <form action="" method="POST">
    {{ form.csrf_token() }}
        <div class="form-group row">
            <div class="col">
                <label for="">Name</label>
                {{'form-control', placeholder='Please enter your name') }}
                <small id="helpId" class="text-muted">Please enter your name</small>
            <div class="col">
                <label for="">Email Address</label>
                {{'form-control', placeholder='') }}
                <small id="helpId" class="text-muted">Enter your email address</small>
        <div class="form-group row">
            <div class="col">
                <label for="">Your message</label>
                {{ form.message(class='form-control', rows='15') }}
        <div class="form-group row">
            <div class="col">
                {{ form.recaptcha }}
                {% for error in form.recaptcha.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            <div class="col">
                {{ form.submit(class='btn btn-primary') }}
{% endblock content %}
Enter fullscreen mode Exit fullscreen mode

The model

from flask_wtf import FlaskForm
from flask_wtf.recaptcha import RecaptchaField
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import Email, InputRequired

email_err_msg = "Invalid E-mail Address"
input_err_msg = "This field is required."

class ContactForm(FlaskForm):
    name = StringField('Name', validators=[InputRequired(input_err_msg)])
    email = StringField(
        'Email Address', validators=[

    message = TextAreaField(
        'Your Message', validators=[InputRequired(input_err_msg)])

    recaptcha = RecaptchaField("Are you real?")
    submit = SubmitField('Send Message')

Enter fullscreen mode Exit fullscreen mode

Just to be thorough..

This is my output in the terminal while the website is running.

The first code clip is a GET request to the /contacts page

Request method: GET
Validation: False
<script src='' async defer></script>
<div class="g-recaptcha" data-theme="dark" data-sitekey="site-key-edited-for-security"></div> - - [06/Mar/2020 16:41:26] "GET /contact/ HTTP/1.1" 200 -
Enter fullscreen mode Exit fullscreen mode

This one is the POST request to that same /contacts page

Request method: POST
Validation: True
<script src='' async defer></script>
<div class="g-recaptcha" data-theme="dark" data-sitekey="site-key-edited-for-security"></div> - - [06/Mar/2020 16:41:42] "POST /contact/ HTTP/1.1" 200 -
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

dmkitui profile image
Daniel Masake Kitui

What version of flask_wtf?

Additionally, are you configuring the RECAPTCHA_PUBLIC_KEY, RECAPTCHA_PRIVATE_KEY in your app initialization???

Update Your DEV Experience Level:


Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. 🛠