Lightweight WordPress Contact Form

This is now available as a plugin from WordPress.

This is the absolute lightest contact form for WordPress. You can add this contact form to your WordPress site either with, or without, a plugin.

  • Jump down to see the plugin installation guide for Lightweight Contact Form plugin.
  • Jump down to use the contact form without a plugin.

I designed this for the fastest page speed and the least amount of server load. So, there is no CSS stylesheet, no extra files, and no overhead.

I wanted a Contact Form plugin that doesn’t slow my site down. Yes, there are some good Contact Form plugins, particularly my other favorite: Fast Secure Contact Form by Mike Challis. However, most existing Contact Form plugins are for people who need customization options.

Sometimes, all I need is a simple contact form to take messages from site visitors. Fast page speed is my priority. With that goal, this plugin is the bare-bones minimum. You must add any CSS styling yourself. See below for some CSS styling suggestions. (In addition, if you need extra fields or different forms for different pages, see the Advanced: Add Custom Form Fields section.)

Although this form is lightweight and simple, it blocks SPAM, and has both client-side and server-side validation. This is a solid and dependable contact form.


  • Emails are sent to the admin email which is set in your WordPress General Settings.
  • Add the contact form to any page with a shortcode.
  • Both JavaScript client-side and PHP server-side validation.
  • No CSS included. This is for the most lightweight footprint.
  • It’s just one file. No extra CSS or JavaScript files.

You can choose from two ways to add this Lightweight Contact Form to your WordPress site: as a plugin, or without a plugin. Step by step instructions for both ways are explained below.

Use The Lightweight Contact Form Plugin

To use the contact form as a plugin, follow these steps.

  1. Install and activate the plugin in your WordPress dashboard by going to Plugins –> Add New. Search for “Lightweight Contact Form” to find the plugin. When you see “Lightweight Contact Form,” click “Install Now” to install the plugin. Click “Activate” to activate the plugin.
  2. Add the contact form to any page, or post, by pasting this shortcode into the page:
  3. Optionally, add the CSS styles which are described below. (jump down to the CSS styles)
  4. This step is strongly recommended. To stop SPAM on your contact form, get your free Google reCAPTCHA keys. Then, enter those keys in your WordPress admin settings by going to Settings > Discussion. On the Discussion Settings page, scroll all the way down to “Lightweight Contact Form” where you’ll find the place to enter your reCAPTCHA v3 Site key and reCAPTCHA v3 Secret key.

That is all. Now you have a lightweight, working contact form on your WordPress site. When someone fills out and submits your contact form, it will be sent to the admin email which is set in your WordPress General Settings.

To try the contact form, visit that page on your site.

If you need extra fields or different forms for different pages, jump down to the Advanced: Add Custom Form Fields section.

Top ↑

Optional – Add CSS Styles

It’s very easy to add CSS to your WordPress site.

Add this CSS to style the error messages and the success message:

#lcf-contactform .lcf_contactform_error,#lcf-contactform input.error,#lcf-contactform textarea.error{border:1px solid #D8000C}
#lcf-contactform label.error,p.lcf-error{display:block;color:#D8000C;background:#ffd2d2;padding:0 10px;height:auto;width: auto;}
.lcf-success-msg {color: #4F8A10;background-color: #DFF2BF;padding:10px} 

Add this optional CSS to align the form fields, if needed (depending on your theme):

#lcf-contactform label {float: left;clear: left;width: 75px;margin-top: 8px;}
#lcf-contactform label[for=lcf_message] {width: auto}
#lcf-contactform input[type="text"] {float: left;width: auto;margin-bottom: 24px;}
input#lcf_contact {margin-top:24px;}

↑ Top

Advanced – Add Custom Form Fields

This section is for people who are comfortable adding code to their WordPress sites.

This section will show how you can have two different forms on your site with this very lightweight code-base. Since version 1.3 of the plugin, you can add custom fields to the form by adding filters.

This example will show you how to add a radio input field to the contact form. In addition, I will show how you can have 2 different forms on 2 different pages. The goal for this example is to have one page with the regular contact form (Name, Email, Message fields), and another page with a form for “Requesting Refunds or Exchanges.”

  1. For the regular contact page, follow the same instructions as bove. This is to simply add the shortcode to a page. Add the shortcode, as is:

    That will be the regular “Contact” page.

  2. Next, we want to create another page where customers can request refunds or exchanges. Create a new page and name it, “Request a Refund or Exchange”.
  3. For this form, we want to change the label for the “Message” field. The “Message” field is where they type in their message. For this form, we want it to be labeled, “Reason For Request” instead of “Message.”

    To change the message label, we have to modify the shortcode. We are going to add the message_label option to the shortcode, like this:

    [lcf_contact_form message_label="Reason For Request"]

    You can change “Reason For Request” to whatever text you like.

  4. Paste the shortcode with the new message_label into the new “Request a Refund or Exchange” page. Publish the page. For the rest of this example, I’ll call this the Refunds Form instead of the Contact Form
  5. Next, we want to add a new field to the Refunds Form. I will add a radio input field where they can specify if they are requesting a refund or an exchange. The radio input field will ask them, “Which one are you requesting?” The 2 radio options are Refund and Exchange.

    Most importantly, I only want this field added to the Refunds Form, not to the regular Contact Form. To make this work, you must get the URL of your Refunds Form since you will need to insert it in the following code. This is the code to add the custom field to the form:

    PHP Code. Add to functions.

     * Add the radio field to the form for Refunds/Exchanges
    add_filter( 'lcf_form_fields', function( $deprecated = '', $url ) {	
    	$form_url = '';
    	if ( $form_url == $url) {
    		$new = '<div id="my-refund-form-field">
    					<label for="lcf_contactform_refund">Which one are you requesting?</label>
    					<input name="lcf_contactform_refund" value="exchange" type="radio">Exchange<br>
    					<input name="lcf_contactform_refund" value="refund" type="radio">Refund<br></div>';
    		return $new;
    	return $deprecated;
    }, 10, 2 );

    Be sure to change on line 6 to the address for your own Refunds form.

  6. Finally, when someone fills out this form, and we get the email, we want the new field to be included in the message. We want to know if the user selected a refund or exchange. The following code will add the new field value to the email message.

    PHP Code. Add to functions.

     * Add the radio field values to the email message
    add_filter( 'lcf_additional_field_values', function( $val, $post_data ) {
    	if ( ! empty( $post_data['lcf_contactform_refund'] ) ) {
    		$new = 'Exchange or refund:  '. sanitize_text_field( $post_data['lcf_contactform_refund'] );
    		return $new;
    	return $val;
    }, 10, 2 );
  7. You may want to add this CSS to align the new field:

    CSS code. Add to Additional CSS in Customizer.

    #my-refund-form-field label {
    #my-refund-form-field {

That is all. Now you have two different forms with a very lightweight code-base.

Top ↑

Add The Contact Form Without a Plugin

If you prefer to add the form without a plugin, follow these two steps. Note that the following code has not added the Google reCAPTCHA v3 functionality, only the plugin has that.

Step 1:

Add this code to your functions. (See how to add code.)

 BEGIN Lightweight Contact Form

/* Check for malicious input */
function lcf_malicious_input($input) {
	$maliciousness = false;
	$denied_inputs = array("r", "n", "mime-version", "content-type", "cc:", "to:");
	foreach($denied_inputs as $denied_input) {
		if(strpos(strtolower($input), strtolower($denied_input)) !== false) {
			$maliciousness = true;
	return $maliciousness;
/* Validate the input, server-side */
function lcf_input_filter() {
	// Block spam bots by making sure honeypot field is empty
	if ( ! empty( $_POST['lcf_hundred_acre_wood_field'] ) ) {
		return false;
	if ( ! ( isset( $_POST['lcf_key'] ) ) ) {
		return false;
	if ( 'process_form' != $_POST['lcf_key'] ) {
		return false;

	global $lcf_strings;
	$pass  = true;
	$lcf_strings['value_name'] = isset($_POST['lcf_contactform_name']) ? sanitize_text_field( $_POST['lcf_contactform_name'] ) : '';
	$lcf_strings['value_email'] = isset( $_POST['lcf_contactform_email'] ) ? sanitize_email( $_POST['lcf_contactform_email'] ) : '';
	$lcf_strings['value_message'] = isset($_POST['lcf_message']) ? sanitize_textarea_field($_POST['lcf_message']) : '';

	if(empty($lcf_strings['value_name'])) {
		$pass = false;
		$fail = 'empty';
		$lcf_strings['name_error'] = true;
	if(!is_email($lcf_strings['value_email'])) {
		$pass = false; 
		$fail = 'empty';
		$lcf_strings['email_error'] = true;
	if(empty($lcf_strings['value_message'])) {
		$pass = false; 
		$fail = 'empty';
		$lcf_strings['message_error'] = true;
	if(lcf_malicious_input($lcf_strings['value_name']) || lcf_malicious_input($lcf_strings['value_email'])) {
		$pass = false; 
		$fail = 'malicious';
	if($pass == true) {
		return true;
	} else {
		if($fail == 'malicious') {
			$lcf_strings['error'] = 'Please do not include any of the following in the Name or Email fields: linebreaks, or the phrases "mime-version", "content-type", "cc:" or "to:"';
		} elseif($fail == 'empty') {
			$lcf_strings['error'] = 'Please complete the required fields.';
		} elseif($fail == 'wrong') {
			$lcf_strings['error'] = 'Oops. Incorrect answer for the security question. Please try again. Hint: 1 + 1 = 2';
		return false;

/* Add the validation script to the footer on the contact form page. */
function lcf_form_validation() {
	?><script type='text/javascript'>var honey = ['lcf-hundred-acre-wood-field','lcf-hundred-acre-wood-label'];
	var len = 2;
	for (var i = 0; i < len; i++) {
		document.getElementById(honey[i]).style.position = 'absolute';
		document.getElementById(honey[i]).style.overflow = 'hidden';
		document.getElementById(honey[i]).style.clip = 'rect(0px, 0px, 0px, 0px)';
		document.getElementById(honey[i]).style.height = '1px';
		document.getElementById(honey[i]).style.width = '1px';
		document.getElementById(honey[i]).style.margin = '-1px';
		document.getElementById(honey[i]).style.border = '0 none';
		document.getElementById(honey[i]).style.padding = '0';
	var submitButton = document.getElementById('lcf_contact');
	submitButton.onclick = function() {
		if(document.getElementById('lcf-hundred-acre-wood-field').value) { 
			return false;
		var hasBlank = false;
		var emailBlank = false;
		// hide previous errors
		[]'.error'), function (el) { = 'none';

		// Check for blank fields.
		var fields = ['lcf_contactform_name', 'lcf_contactform_email', 'lcf_message'];
		var i, l = fields.length;
		var fieldname;
		for (i = 0; i < l; i++) {
			fieldname = fields[i];
			var el = document.forms['lcf-contactform'][fieldname];
			if ( el.value.trim() === '' ) {
				lcfErrorLabel(el, fieldname, "u2191 <?php echo 'This field is required.'; ?>");
				hasBlank = true;
				if ('lcf_contactform_email' == fieldname) {emailBlank = true;}// is the Email field blank?

	    if (!emailBlank) { // if Email is entered, validate it
	    	var eNode = document.forms['lcf-contactform']['lcf_contactform_email'];
		    var filter = /^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$/;
		    if ( ! filter.test( eNode.value.trim() ) ) {
				lcfErrorLabel(eNode, 'lcf_contactform_email', "<?php echo 'Invalid email. Please enter a valid email.'; ?>");
				hasBlank = true;

	    if (hasBlank) {scroll(0,0);return false;}

	function lcfErrorLabel(el, fieldname, text ) {
		var err = document.createElement('label');
		err.setAttribute('for', fieldname); 
		err.className = 'error';
		err.innerText = text;
		el.parentNode.insertBefore(err, el.nextSibling);

/* Shortcode to display contact form */
function lcf_shortcode( $atts ) {
	$the_atts = shortcode_atts( array(
		'message_label'	=> 'Message'
	), $atts, 'lcf_contact_form' );

	if (lcf_input_filter()) {
		return lcf_process_contact_form( $the_atts );
	} else {
		add_action( 'wp_footer', 'lcf_form_validation', 9999 );
		return lcf_display_contact_form( $the_atts );
add_shortcode( 'lcf_contact_form', 'lcf_shortcode' );

/* Process contact form */
function lcf_process_contact_form( $atts ) {
	global $lcf_strings;
	$subject = sprintf( 'Contact form message from %s', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) );
	$name = isset( $lcf_strings['value_name'] ) ? $lcf_strings['value_name'] : '';
	$email = isset( $lcf_strings['value_email'] ) ? sanitize_email( $lcf_strings['value_email'] ) : '';
	$message_label = esc_html( $atts['message_label'] );
	$message = isset( $lcf_strings['value_message'] ) ? $lcf_strings['value_message'] : '';
	$form = esc_url( getenv("HTTP_REFERER") );
	$date = date_i18n( get_option( 'date_format' ) ) . ' @ ' . date_i18n( get_option( 'time_format' ) );
	$filter = apply_filters( 'lcf_additional_field_values', false );
	$intro = sprintf( 'You are being contacted via %s :', $form );
	$fullmsg = ("Hello,


Name:      " . stripslashes( $name ) . "
Email:     $email

" . stripslashes( $message ) . "


	wp_mail( get_bloginfo('admin_email'), $subject, $fullmsg, "Reply-To: $emailn" );

	$results = '<div id="lcf-success"><div class="lcf-success-msg">Your message has been sent.</div>
<pre>Name:    ' . stripslashes( esc_html( $name ) ) . '
Email:   ' . esc_html( $email )   . '
Date:    ' . esc_html( $date ) . '
' . $filter . '
' . $message_label . ': ' . stripslashes( esc_textarea( $message ) ) .'</pre><p class="lcf_reset">[ <a href="'. $form . '">Click here to reset form</a> ]</p></div>';
	echo $results;
/* Display contact form */
function lcf_display_contact_form( $atts ) {
	global $lcf_strings;
	$lcf_form = '';
	$url = get_permalink();
	// entered values
	$name = isset( $lcf_strings['value_name'] ) ? sanitize_text_field( $lcf_strings['value_name'] ) : '';
	$email = isset( $lcf_strings['value_email'] ) ? sanitize_email( $lcf_strings['value_email'] ) : '';
	$message = isset( $lcf_strings['value_message'] ) ? sanitize_textarea_field( $lcf_strings['value_message'] ) : '';

	// set class attributes for fields based on whether there is an error
	$fields = array( 'name', 'email', 'message' );
	foreach ( $fields as $field ) {
		${"{$field}_class"} = empty( $lcf_strings["{$field}_error"] ) ? 'required' : 'lcf_contactform_error';

	if ( isset( $lcf_strings['error'] ) ) {
		$lcf_form .= '<p class="lcf-error">' . esc_html( $lcf_strings['error'] ) . '</p>';


	$lcf_form .= '<div id="lcf-contactform-wrap">
			<form action="'. esc_url( $url ) .'" method="post" name="lcf-contactform" id="lcf-contactform">
				<label for="lcf_contactform_name">Name</label>
				<input name="lcf_contactform_name" id="lcf_contactform_name" type="text" size="33" class="' . esc_attr( $name_class ) . '" maxlength="99" value="'.
				stripslashes( esc_attr( $name ) ) .'" placeholder="Your name" required />
				<label for="lcf_contactform_email">Email</label>
				<input name="lcf_contactform_email" id="lcf_contactform_email" type="text" size="33" class="' . esc_attr( $email_class ) . '" value="'. esc_attr( $email ) .'" placeholder="Your email" required />';
	// add a honeypot field to block spam
	$lcf_form .= '<label for="lcf-hundred-acre-wood-field" id="lcf-hundred-acre-wood-label">' . __( 'For Official Use Only', 'lightweight-contact-form' ) . '</label><input name="lcf_hundred_acre_wood_field" type="text" id="lcf-hundred-acre-wood-field" value="" tabindex="-1" />';
	// filter to allow insertion of more fields.
	$lcf_form .= apply_filters( 'lcf_form_fields', '', $url );
	$lcf_form .= ( '<label for="lcf_message">' . esc_html( $atts['message_label'] ) . '</label>
				<textarea name="lcf_message" id="lcf_message" minlength="4" cols="33" rows="7" placeholder="Your message" class="' . esc_attr( $message_class ) . '" required>'. stripslashes( esc_textarea( $message ) ) .'</textarea>
				<div class="lcf-submit">
					<input type="submit" name="Submit" id="lcf_contact" value="Send">
					<input type="hidden" name="lcf_key" value="process_form">
		</div>' );
	return $lcf_form;
 END Lightweight Contact Form


Step 2:

Add the contact form to any page, or post, with this shortcode:


That is all. Now you have a lightweight, working contact form on your WordPress site. Jump to see CSS styling suggestions.

Top ↑

See more:

We've 15 Responses

    • March 9th, 2016 at 1:17 pm

      The contact message will be sent to the “admin email” which is the “Email Address” set in your WordPress dashboard –> “Settings” –> “General”. If you want set a different email address in the code, edit line 186. On that line, enter your desired email address as the first parameter of the wp_mail function. So, replace just this part of line 186:


      with your own desired email address.

      Hope that helps.

  1. April 6th, 2017 at 12:21 pm

    Thank your for your form. It is great!
    On my contact-page gets a 100% Performance grade.

    I have 2 questions.
    When the e-mail is sent it says WordPress ( in the from-field. How can I change that.

    Can you tell me how I can add an extra email with bcc?

    The Netherlands

    • April 6th, 2017 at 5:27 pm

      Hi. Thank you. Yes, it uses the default WordPress functionality, which is to send from “” You can change this by replacing line 186.

      Remove line 186, and paste this instead:

      $headers[] = 'From: My Name <>';
      $headers[] = 'Bcc: John Doe <>';
      $headers[] = "Reply-To: $email";
      wp_mail( get_bloginfo('admin_email'), $subject, $fullmsg, $headers );

      Replace My Name with your desired “From name” and replace John Doe with the name of who the person to Bcc. Replace both email addresses on the first 2 lines. (Leave the surrounding brackets in place.)

      Please note:

      Many web hosting companies require the “from email” to be an email at your actual website. For example, if your website is, then your “from email” must be

      If you have that type of web host, the mail will not send if you use a “From email” address that is not hosted on your site, for example Gmail or Yahoo email. If this does not work for you, then you can try the WP Mail SMTP plugin. That plugin always makes this work.

      I hope this helps.

  2. January 8th, 2019 at 5:51 am

    Thank you so much for this plugin. I love how fast it is and easy to use. I’m getting a ton of spam comments though. Is there some anti-spam feature, such as a checkbox or something that I can add to reduce the number of spam comments?

    Please advise. Thank you.

    • January 9th, 2019 at 7:30 pm

      Thanks. I just updated the plugin to version 2.0 which adds the ability to use Google reCAPTCHA v3 to stop spam.

      To make use of the extra spam protection from Google reCAPTCHA v3, you must get your reCAPTCHA v3 API keys from Google. Then, enter those keys in your WordPress admin settings by going to Settings > Discussion. On the Discussion Settings page, scroll all the way down to “Lightweight Contact Form” where you’ll find the place to enter your reCAPTCHA v3 Site key and reCAPTCHA v3 Secret key.

  3. February 17th, 2019 at 3:45 am

    Hi Isabel.

    Thank you very much for this Plugin.

    Have you any suggestions on how to add a checkbox because of GDPR compliance?

    Best regards,

  4. August 1st, 2020 at 11:11 pm

    Thank you, Your code works great for a lightweight form, I added in the api for my subscription service so that the contact form is mailed to me and the visitors can join our subscriber list. Works great.

  5. January 3rd, 2021 at 1:55 am

    The plugin works beautifully, and would benefit by the addition of a unique class name for each error field to enable independent error message positioning and styling.

    I ask because I changed the css to have the name and email fields on a single line, and the error messages were not positioned beside their respective fields.

    While the plugin worked perfectly, when I tried adding the code to my functions instead of using the plugin, no error messages displayed. I suspect the “add the contact form without a plugin” seciton is out of sync with the current version of your code.

    Thank you in advance for your help in enhancing the plugin.




Leave a Reply to Afeef Cancel reply

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this: