Building a PHP Contact form with Captcha from scratch

Web projects are divided into back-end and front-end work, so web designers don’t have to worry about the “scary” programming, but what about simple presentational websites, where web designers can single-handedly work on, but inevitably get stuck on the contact page.
At that point, most either ask a PHP programmer to do the contact form’s PHP processing or implement an open source contact form somewhere from the web.

But! What if we learn how to actually create one from scratch, eh?
Not only it would help you easily manage smaller projects, but also have a better understanding how PHP form validation and processing works and can help you better tweak other scripts out there.

Now, there are countless ways to build and validate a form, but for this lesson’s sake, I’ve chosen to build most of the code in a single contact file, plus, it will give us one small benefit at the end, you’ll see. :)

So let’s get started! Right below, you have a basic non-fancy HTML contact form.



  • Things to know:
    • Our contact page has the .php extension so it can expect and process PHP code;
    • The form has an ‘action’ attribute, it specifies the file that’s going to send the form’s data to, since we’re going to do most of the work inside the same document, we specified the current document: contact.php;
    • The attribute ‘method’ is the way we want our data to be handled and sent, we specified ‘POST’ as it’s a more invisible way to send the data, the alternative is ‘GET’, though GET will display the data in the URL and we don’t want that;
    • All HTML form fields have a ‘name’ attribute, PHP uses the values from the name attributes to fetch their data.

We need to make sure that our PHP code will only be run if the form has been submitted, to do so, we’re going to insert our code inside a PHP function that detects whether the visitor has clicked or not the submit button.

From this point on, we’ll start checking whether all fields have been filled and add them to variables which we can further use, or add errors in case of non-filled fields.
We’ll need an empty $error variable which we can add the error messages to in case there will be any:

We have ‘name’ as the first field, let’s validate it by adding:

Like I mentioned earlier, we’ve used the POST method to handle the form’s data, we can fetch the fields’ values by using $_POST[‘name_of_field’], also, we used the ’empty’ PHP function to check whether the fields are empty or not. The litteral translation of the above code would be: IF the name field is not empty, then add the name field’s value to the $name variable, but if it’s empty (ELSE), then add to the $error variable “You didn’t type in your name. <br />”. Knowing that we may have more field errors to display, all messages have a break tag at the end so each will be displayed on a new line.

Validating the e-mail address field is going to be a bit more tricky, because not only that we have to check whether the visitor has inserted one, but also if it’s a valid e-mail address:

Don’t panic! That whole preg_match “mumbo-jumbo” haha, is actually a line of code you might never have to change when validating e-mails. Don’t worry about remembering the exact code, even skilled programmers have it saved somewhere ready to copy paste 😛
Now, the only difference from the name validation code, is that we added a secondary IF statement to also check whether the e-mail entered is valid, that being done with the preg_match function.
If you’re interested to know though, preg_match uses given regular expressions against a value and returns whether it matches or not. In our case, we used preg_match to make sure that:

  • the email value’s first char starts with a letter between A-Z, or a number between 0-9
  • the rest can also contain a dot, dash or underline
  • must be followed by an @
  • the rest can contain all letters, numbers, a dot, dash and underline
  • must have a last dot which can be followed by an extension of 2 or 3 chars
    • if it doesn’t match then add to our $error variable an error message.

But like I said, you can save that preg_match function somewhere and use it whenever you want to validate an e-mail field/value.

Next up and last field is the ‘message’ textarea, we validate it just like we did with the ‘name field':

And that’s a wrap with the fields validation, here’s what we have so far:

There’s just one step left to do, determine whether the form has been filled properly and send the message, or the visitor encountered errors.
Here’s the logic, along the validation process, in case the visitor has failed to either fill in all the fields or add a valid e-mail address, we added error messages to the $error variable, all we have to do is check whether the $error variable has messages in it, basically, if it’s empty or not. If it’s indeed empty, we can go ahead and prepare to send the message:

Sending an e-mail with PHP’s mail() function is quite easy as you can see in the last line of code, all we need to know is where to send it, the e-mail’s subject, the content and where it came from. We’ve added the needed variables including the success message. Make sure you change ‘’ with yours.

Though the above code won’t be executed if the visitor has encountered errors, thus $error no longer is empty. We need to determine where we want to add the error messages, I personally want them between the h2 tag and the form:

Yet, just another ‘if-and-else’ statement where we check if $error is not empty and echo the $error messages we added along the way, else (if it’s empty), then the mail was sent and we echo the $success variable which we added previously.

And there you have it, a functional PHP contact form! Here’s the final code:


If you’ll look at the HTML form again, you’ll notice some PHP code in the fields.
Many complain that PHP is not a good main form validator, because it clears the form even when the visitor encounters errors and has to refill it again. Well, not exactly, because we added the PHP processing in the same file with the html form, we now have access to the fields’ values via $_POST[‘name_field’]; and we can assign those values back in the fields. Voila, no more form refill stress!

The form is now fully functional, you can use it assured, but I say something’s missing. Guessed it? SPAM protection!
Nowadays, you can’t put up a public form without receiving countless spam e-mail messages.
You can either stop here, or quickly learn how to add captcha protection to the form.

We’ll make the captcha script in a separate file called captcha.php and we’ll also need to make a few minor changes to contact.php afterwards.


I’ve added comments on each line and I believe the code is already self-explanatory and you can tweak the values as needed. What’s to notice, is that now we’re using sessions so we can save the generated code on the server and validate it in the form, similar to how we used $_POST[‘name’];
The files that work with sessions, they need to start with session_start();, that really has to be the very first line the document starts with, nothing must come before it. So both captcha.php and contact.php need to have <?php session_start(); ?> at the very beginning.
Now we need to add another HTML form field for the captcha, right before the submit button:

We used captcha.php as the image source, because, well… it is an image. The captcha PHP script we’ve made generates an image and captcha.php behaves like one.
Lastly, we’re going to validate the code that the visitor enters, like we did with the other fields, we’re going to add another ‘if-and-else’ statement below the other ones:

Looks familiar? Not far from validating the name field I guess, we fetch the code the visitor enters using POST and validate it against the code we saved it on the server via $_SESSION[‘code’];, if it fails to validate, just add another error message to $error. And that’s a wrap!

Here’s the final code with captcha:




To add more required fields in the form is quite easy, for example, if we’d need one more field for the visitor’s phone number, we’ll add another html form field:

Another if-and-else statement along the others:

And add the $phone variable in the content variable which gets sent:

The code is 101% free to use, a backlink is optional but highly appreciated, it would give this article more exposure to other readers out there :)


My name is Cătălin Berța and I'm a front-end web developer. I was born in Focsani, Romania and currently living in Bucharest. Started playing with some good old html tables ever since 2004 as a hobby, turned out to be a full-time career! :) I've had the chances to experience and witness web development's rapid growth over the years where I've mainly focused on front-end web technologies.

191 thoughts on “Building a PHP Contact form with Captcha from scratch

    1. Thank you! I did try to get into as much details as possible, I was, however, worried at some point not to make my readers dizzy heh, I’m glad you enjoyed it.

    1. I’ve tried to keep the entire process as simple as possible, using a more advanced captcha system worried me that it might confuse the readers along the process :)
      I’ll, however, consider writing a separate article about a more complex captcha, though this one should do just fine, unless you’re running a highly solicited web company 😛
      Thanks for the feedback!

  1. I went through the process quite thoroughly, and after understanding each and every part, and constructing my files, I cannot get it to execute! Have any suggestions? Your article was very good and explained very well. I thought I could execute php file if I had php executable specified, but I keep getting code in all the fields. Thx much.

    1. I assume you’re trying to run the php files locally on your computer. To do that, you’ll need to install a local web server, you can achieve that by installing the WAMP server for windows or LAMP for Linux, there’s also XAMPP which has support for all operating systems. An easier way would be to run the files on a hosting account.

  2. Really great article on building a PHP contact form from scratch. I particularly liked how you gave the examples and diagrams, they were very useful.

  3. Thanks Buddy! I truly enjoy the information that? you’re sharing bruh! Extremely simple to comprehend.

  4. This post is very interesting, I like it. I will always come to visit after.I would recommend to friends more.

  5. Pingback: Here’s your gift – free elevator pitches! | Free Blog Help
  6. Hello there, I trust you, should you found yourself in Romania you’ve got a light beer via us: ) Regards!

  7. Hi, currently making a website with a contact form page, I’ve got my page layout all done and called it contact.html, i’ve copied you css into my style sheet, copied the captcha page and inserted all the php into my page where i want the form, but when the form comes up it’s covered in php script, i’m guessing this is because all the files are in the same folder? What does it mean that it’s server side aswell, when i try open it? You don’t have to explain that bit though, ill try find an article on it.

    Thanks for the post though, it’s help me a lot, sure I’ve just missed something!

    1. That’s because you haven’t renamed your contact.html file to contact.php
      PHP will only be parsed if the file extension ends in .php
      So go ahead and rename your contact page and it should work just fine!
      Let me know how it turns out for you

  8. Hi – thanks for getting back to me so quickly. Just tried that but still getting the same problem,

    All this text is over and around the form:

    “Your message was NOT sent
    The following error(s) returned:
    ‘ . $error . ‘

    ‘; } elseif (!empty($success)) { echo $success; } ?>
    Name: Email: Message:

    Along with some other php script in the text fields. Been using HTML and CSS a few years, but this is the first time I’ve wanted to make a contact form and worked with PHP.

    1. I just went on and assumed you were running your files on a hosting server or a local one for that matter, but I guess you’re not. PHP can’t be run without apache/PHP.
      If you have a hosting account, run your files there and they should work. If not, try XAMPP, it’s a free local web server which you can do all of your PHP/MySQL work under.
      Best of luck!

  9. I have successfully added your form in my web site. But i found a small mistake. Email’s that have ” _ ” are not valid
    for example:
    and yet such emails exist.

    Could u send me just that corrected part of the code via email.
    Tnx in advance.

    1. Ah yes! Thanks for noticing that Igor, it looks like I’ve missed the first underscore rule. Here’s the new pregmatch expression:
      (!preg_match(“/^[_a-z0-9]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i”, $email))

      The files have been updated here as well.

      Post back if this worked for you :)

  10. great script, one of the best so far I’ve found online 😉 .. but i have some questions regarding space:

    how can i combine the php “value” variable:
    <input type="text" name="email" value="” />

    with this variable:

    I don’t want to have the description outside of my form fields but I’d like to have them inside since i do not have that much space on the website.

    furthermore – what is the correct pregmatch expression for checking the phone number field and only allowing “0-9″ (?!):
    (!preg_match(“/^[0-9]/i”, $phone))

    i deeply appreciate your support.
    thanks again

  11. PS: here again since it seems it killed the script 😉 hope this works now ..

    great script, one of the best so far I’ve found online 😉 .. but i have some questions regarding space:

    how can i combine the php “value” variable:
    input type=”text” name=”phone” value=”(?php if ($_POST[’email’]) { echo $_POST[’email’]; } ?)

    with this variable:

    value=”Your Phone Number” onFocus=”if (this.value == ‘Your Phone Number’) this.value = ”;” onBlur=”if (this.value == ”) this.value = ‘Your Phone Number';”

    I don’t want to have the description outside of my form fields but I’d like to have them inside since i do not have that much space on the website.

    furthermore – what is the correct pregmatch expression for checking the phone number field and only allowing “0-9″ (?!):
    (!preg_match(“/^[0-9]/i”, $phone))

    i deeply appreciate your support.
    thanks again

    1. I’m glad you liked it Cybo!

      To validate an ‘only numbers’ field, you can use (!preg_match(“/^[0-9]/”, $phone)) yes

      I’m not sure you really want to be so strict about phone number validation, such as forcing a format xxx-xx-xxxx etc I personally had too many complaints how clients couldn’t manage adding the phone number to a form :)
      One thing you can do though is to force it to a certain length, if you know your visitors’ phone number area, then just ask for a certain length:
      (!preg_match(“/^[0-9]{10}/”, $phone))

      The number in between those curly brackets requires the value to have a 10 number length number and you can eventually add an example of a phone number they’re able to add.

      Regarding your other inquiry, I’ll e-mail you, too much for a comment 😛

      Good luck!

      1. hey catalin.

        awesome! thanks for your reply. i didn’t receive en email by now, so please use the one off this post 😉 this should arrive for sure!
        Great input. I only wanted to validate “numbers only” – since you are right a too tough restriction might end up in a customer “jump off” mentality 😉

        have a wonderful sunday!

  12. Hey, quick question about the captcha, I followed your tutorial to the letter, and made sure that I understood each part before moving on. My only problem is that when the captcha is correct there is an error, but when the captcha is wrong, the message is sent. With my limited knowledge of php, I am having a hard time figuring out why this is, especially because my code is identical to yours and is correct as far as I understand it. Any ideas would be gratly appreciated.

    1. please disregard my previous comment, I had simply forgotten to start my contact page with the php session_start(). Thanks anyway.

  13. Even though I am not good at customizing/developing a site, but I know how to admire the works of a skillful web developer. And the article that you have posted here is very informative and compelling. And I might try myself it too.

    1. In the PHP code add two more variables:

      $ip = $_SERVER[‘REMOTE_ADDR’];
      $browser = $_SERVER[‘HTTP_USER_AGENT’];

      Those will detect the IP and Browser user agent and add them to those variables (which you can name however you want).
      All you have to do now is include those variables in the e-mail’s $content variable.

      $content = $name . ” has sent you a message: \n” . $message . “\n IP: ” . $ip . “\n Browser:” . $browser;

      And now the e-mails will also contain the sender’s IP address and browser agent.

  14. Excellent. Now how do I get the form fields to go away and show only a success message after a successful sent?

    1. This contact page has not been constructed to do that, however, it’s not hard! But not that easy to explain in a comment either. I’m willing to mail or chat the solutions with you.
      I’ll e-mail you several ways we can communicate.

  15. I got it working for the most part. Although I’m having a problem with the captcha.

    I enter the right code but I still get an error that says the code is incorrect.

    1. I believe you missed a vital step, if you read carefully, I’ve mentioned that your contact page needs to start with:

      < ?php session_start(); ?>

      See if that fixes the problems :)

  16. Hi, great tut and thanks for sharing.

    I think I understand everything but seem to be having the same trouble. I have at the top and tried changing CHMOD but still not validating the captcha.

    On the latest version of my xampp local host, the form works fine but the email doesn’t get sent. When uploaded to a web server all variables work except the captcha doesn’t validate and email is only sent when field is empty.

    Anything else come to mind?


    1. I will have to ask again, are you absolutely sure your contact.php page starts at the very beginning with < ?php session_start(); ?> ? No spaces before it, nothing.

      If you’re sure, then perhaps you can send me your files to catalin (at) devingredients (dot) com, so I can figure out where you messed up 😛

      Also, always test your final contact form on a real host, xampp and other local servers do not send e-mails unless properly set to do it.

      Looking forward to hearing from you.

  17. Thanks Catalin,
    So I double checked to make sure there’s no spaces and that session_start is at the very beginning of the page. Yea I kinda figured I didn’t set up outgoing on my local.

    I sent the site files for the contact page. Thanks so much for your help, It’s greatly appreciated!


  18. So the form trouble got solved. It was in fact a hosting server issue. I had to edit the session.save_path for my account and edit the .htaccess file. The form works great. Thanks for sharing this and for all of your help.


  19. I seem to be having the same problem as the gentleman above. My contact form is included into my entire layout through a php script (to have pages like index.php?page=contact). For one, the form action needs to be removed as it does not work with index.php?page=contact.

    This means I need to open my session on the index page, which isn’t a problem. However when browsing to the contact form (thus loading index.php and having contact.php included through a require(), it keeps coming up saying the code is wrong. When I however enter an incorrect code or just press send after having gotten the error the code is wrong, it sends the message just fine. Pretty frustrating.

    I *could* use the form without the captcha, but I’m worried to be receiving a lot of spam.


    1. That’s the exact reaction as if the page does not have session_start at the beginning. Knowing your method of dealing with the site’s inner pages, it’s a bit difficult figuring out what can cause that. If the site doesn’t contain sensitive data, you can try mailing me the files so I can test them myself, perhaps clearing the content before sending them.

      1. I can mail you the website. It does not contain any sensitive information. If you give me an e-mail address then I will mail the entire website zipped (or rarred, whichever you like).


  20. Can a dropdown be added to the code ?

    For exampleif you want to ask-

    How did you find us(below are the options to give)

    from a friend
    search engine
    dumb luck
    saw the link at another place


    1. That’s very easy friend, question is though: Do you simply want to have the dropdown selection sent in your e-mail (regardless if it was selected or not), or to validate the field and force the user to select an option?

      The process to add a dropdown is the same as you do with inputs. At the end of the tutorial I explained how you can add extra fields and what extra PHP code is needed, just add a dropdown instead :)

      < select name="source" >
      < option>< /option >
      < option>From a friend< /option >
      < option>Search engine< /option >
      < option>Dumb luck< /option >
      < option>Saw the link at another place< /option >
      < /select>

      P.S. Don’t copy the above code, I added extra spaces to evade code parsing.
      The reason I added a blank option at the beginning is so the user can get an error in case (s)he didn’t select an option.
      If you don’t wish to force the user to select an option, then just remove the blank option and add a default one (i.e. < option > No selection < /option >)

      Now, let me know if you manage, if not, I’ll probably help you via e-mail.


  21. By the way,this is by far the best and easiest tutorial how to make a form using captcha and php that I come accross.

    It took me a while to find it but I did and the onlything I would consider adding to it would be as my previous post asks,the ability to put a select list dropdown or a radio/checkbox(which could have multiple answers selected)

    Awesome job explaining and linking mockups for us to use.



  22. I got the select form to work just fine .thank you for that.

    I was also wondering how I would have to do the code to select from a list of choices (check boxes and get multiple answers returned.(such as checking all that apply …)



  23. Hi i’ve installed wamp and im getting errors and code is beuing displayed in the text boxes.. am i doing something wrong

    1. Not at all. Only wamp displays those errors.
      If you’ll run the files on a public hosting server, the form should work just fine.
      Also on wamp, if you’ll submit the form leaving the fields empty, the errors inside the boxes will disappear.

      This can be fixed and I’ll update the files very soon.

  24. I have incorporated your contact form into my contact page. However, when I try to send an e-mail, I keep getting the error about captcha code not matching . . . ?

    ? has been included on contact.php page.

    I sincerely hope you can help! Thank you so much for your time.


        1. With that in mind and with the code in this blog, it should work. So there must be something on your page that stops the form from processing the verification code. I’m willing to take a closer look at your code if you’re willing to send the page (and the related script/php files) over at catalin (at) devingredients (dot) com
          Remove confidential info as needed.

  25. Is there any way to make this clear the form data once its submitted. The form action is pointing to the same page as the contact form, since everything on my site is on one page. So after submit the data gets sent fine and thank you message is displayed however the data still remains. I know usually you could do something like value = “” so when page loads form data would be blank for each item, however since value points the php variables I’m not quite sure how to clear. Any help would be appreciated. Thanks

    1. You’ll notice that as long as the form is submitted and no errors are given, a few variables are written. We can check if one of those variables exist, if they do, that means the form will get sent and we can stop PHP echoing the data in our form fields.
      So let’s just check whether the $success variable is empty and only echo data as long as it’s not, since $success is written only when the form gets submitted successfully.
      So our name field would be come from this
      < ?php if ($_POST['name']) { echo $_POST['name']; } ?>
      to this
      < ?php if ($_POST['name'] && empty($success)) { echo $_POST['name']; } ?>

      Do the same for the other fields.
      So now they’ll be filled as long as the form does not get sent.

      Let me know if you manage.

  26. Hi Catalin,I see some site changes-mostly color and I like it.Keep up with the awesome tutorials.I do appreciate all of the help you provided me in making my feedback form

  27. Thanks bud! It was a pleasure helping you.
    I thought it was time for a change and I like how this theme is turning out as well. “The beautiful gray!”

    Looking forward to having more free time to focus on the blog.

  28. I have always struggled with contact forms, but today I created my own for a work project, and it is slick! Couldn’t have done it without this tutorial. Nice work!

  29. Thanks for creating this tutorial. I followed the guide and created the contact form, after going live with the page, I enter my contact info and message, hit send and get the Thank you, message was sent. It all appears successful. But the messages are not arriving at the specified email address. Not trapped in spam folders either. Anyway ideas to troubleshoot?

    1. You’re very welcome!
      Did you make sure that your contact page starts at the very beginning with < ?php session_start(); ?> ?
      Try adding a wrong captcha code intentionally, does it still succeed?

      I can have a look at the code if that’s alright with you. Have all the necessary files zipped and sent to catalin (at) devingredients (dot) com


  30. Hi, thanks so much for the coding. I’m setting up a site and trying to configure it. I thought I did it right but when I enter the info in and press send, it always says the capcha is wrong when it isn’t. What am I doing wrong?

    The page in question is located here:

    Any help greatly appreciated. Thanks in advance.

  31. Also, just wondering if you would be so kind as to share how you got feedburner to pop up with the subscription when I entered my comment too? And if you are willing to share, would it work with Disqus on a blog? Thanks again.

  32. This is a great clean form and exactly what I was looking for for a site I’ve been working on. I am having a problem though. I am 99% sure I have copied everything exactly, but when I fill it out, with or without correct required info… nothing happens, it doesn’t send, there are no error messages or anything.

    I am running it from a web server, so that’s not the problem.

    I have changed it slightly to fit my stylesheets and a different layout. Also I am calling it from an iframe in my contact.html page (I’ve renamed this form.php) – BUT even if I try all the code combined in a contact.php page as per the tutorial I still get nothing happening when I hit ‘send’. It just refreshes the page.

    I have put this part on hold for now until I have a chance to figure it out, but perhaps that sounds like some easy problem to fix? I hope so

    1. @Steve
      Sounds like a very strange behavior, would you be kind and send your files to catalinberta (at) devingredients (dot) com? I can take a look.

      This form is quite basic and it’s obviously not the most secure web form to use :-) It is recommended for new developers to get a fast contact form up and running. Thankyou :)

  33. I really appreciate the tutorial. I’m an aspiring PHP developer and stayed away from captcha codes b/c they seem too complicated but you made it really simple to understand. Thanks so much. I would like to see you approach to defend from code injection, which is a somewhat common problem for web forms as well. Thanks a million.

  34. Hello, I have a question, if you go to there is a test website with a contact form on the contact page created with this code, it works perfectly but! when i upload the contents of this website to another website, it wont work -___-”

    then all of a sudden i get php code in the top and bottom of the contact page.

    Can you help me with this?

  35. this is the code i get:

    Warning: session_start() [function.session-start]: open(/public/tmp/sess_8cecfd11ce372198728ab0a26b8f8cb9, O_RDWR) failed: No such file or directory (2) in /public/sites/ on line 1

    Warning: session_start() [function.session-start]: Cannot send session cookie – headers already sent by (output started at /public/sites/ in /public/sites/ on line 1

    Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent (output started at /public/sites/ in /public/sites/ on line 1

  36. I found using this, even though to captcha was not entered and correctly it threw the message that the captcha did not match it still sent the form to my preferred email address why is that?

  37. @Stephen Mills
    Most likely because you have not started your contact.php file with < ?php session_start(); ?> at the very beginning. See if that fixes things.

  38. Thanks for the code.
    Am looking for a way to use data stored in an sql table to verify form field entry before it is submitted. For instance, I want the form to compare the entry in its “user Id” field with the contents of the column of a database table named “user_Id” which contains serail numbers of all users who are authorised to submit the form. Such that the form can only be submitted if the entered “User Id” mtches one of the entries in the database column.

  39. @catalin Thank you I fot to surround session_start(); with , thank you for a very simple form, as i’ve just started out on PHP it nice to have a well planned out form with the ability to easily change layout and style with CSS, 12/10 :-)

  40. @Spiros Mantadakis

    Are you uploading the exact content on another server? Or you’re embedding the contact form in another website via include, iframes etc? Because session_start(); must be at the beginning of the main page that holds the contact form and if this is the case, session_start should not be called again.

    According to your error, it might be because you called session_start twice.

    Also, make sure your hosting server allows SESSIONS.

    Let me know how things turn out for you.

  41. HI
    I am trying your captcha email form. But the captcha does not work properly. When I fill out the form, it gives me the error that the captcha code was incorrect. This continues forever. So the form does not get sent.

  42. Hello,
    To contact an advert owner, the users will have to fill a contact form which will be send to the owner email(hotmail,yahoo,…), but the php script is hardcoded so how i will be able to do it?is it possible to write a script which can be use for all the contact form without modifying it each time a user is contacting different Ads owner?please can anybody help me out!!!…
    Thank you.

  43. Hello Bro:

    I tried my level best to send a message with work you have done, i am not sure why i get a warning message as: Warning: mail() [function.mail]: Failed to connect to mailserver at “localhost” port 25, verify your “SMTP” and “smtp_port” setting in php.ini or use ini_set() in C:\wamp\www\bgold\contact.php on line 46.
    also all the text boxes are mixed around… it is my first project and i will really appreciate your help.

  44. Hi Catalin,

    I have used your code on my website, which is still in the construction phase, and it works very well! In addition, I find the way you break down the coding to be very helpful in my learning, so I would like to buy you a beer. Please send me a link for paypal or some other payment method and I will send you 10 euros/dollars for a beer. I will be checking out more of your code, so you’ll probably become an alcoholic over time 😉

    Thank you,


  45. Even though I am not good at customizing/developing a site, but I know how to admire the works of a skillful web developer. And the article that you have posted here is very informative and compelling. And I might try myself it too.

  46. @Joe
    I’m glad I was of help to you and I appreciate your initiative, you’re awesome!

    Thank you!

    @Open Source Development
    Perhaps a dropdown menu with a list of owners might do the trick. The dropdown behaves like the input, php processing-wise.

    @Nisar, that’s because you’re probably running everything on a local server, try running the code on a live hosting account :)

  47. Hello,

    Great code. Easy to use and fit into my current HTML/CSS configurations.

    One problem I’m having, though:

    The code works. I send an E-mail, with the captcha code entered correctly, and I get a success “Your message has been sent” message. But I’m not getting the E-mail at the addressed I specified in the contact.php page.

    My host does not disallow the use of mail(). Any ideas as to what the problem might be? Thanks much!

  48. Hi,

    Thank you very much for the code i really appreciate that but I have one little problem with sending the email.

    I’ve did all the steps with cautious and everythin is doing well, but the e-mail is not coming into my e-mail (i’ve checked spam too). The form is ending with a message “Thank you! Your message has been sent!”, captcha’s working but no e-mail appearing in inbox. Im testing it on public hosting service. Any thoughts what may cause that? Forward thanks

  49. @versedi

    Sounds like it should work indeed, like I’ve done before, I can take a look at the files, if you’re willing to send them to me of course: catalin (at) devingredients (dot) com

    Remove any confidential data please :)

  50. Is it possible to have the errors of a wrong field requirement show up beside or under the form field instead of on a new blank page?

  51. @James
    The current code does not open a new blank page, it reloads the same page and displays the errors.

    If you’re, however, referring to error display without page reload, then you’d have to, as a solution, validate the form with JavaScript and that’s not covered in this tutorial, I could make a separate tutorial with that if I get requests.

  52. My bad. I thought that my email address would be available when viewing the page source code, but it’s not. Thanks again for the great code. It works perfectly!

  53. Hi again @catalin sorry to bother you again, is there anyword with the Captach image works in Chrome as recently using chrome the captacha image loads find then 3 secons later it crashes, it works in Firefox, latest IE, opera, safari, just chrome it crashes in, as it works in all the rest I don’t know where to start. is anyone else having this problem?

  54. Also I just reloaded the page, quick jotted down the capatcha code within the 3 seconds, filled out the form and submitted it, kindly had the message saying it was sent, as you know the form reloads itself with a new capatcha code but this time it doesnt crash? it’s odd :-/

  55. @Stephen Mills
    I have done various tests with several versions of chrome and I can’t seem to reproduce this error you’re having. I’d like to know the Chrome version you’re using and the operation system you’re on and I’ll try to get to the bottom of it.

  56. @Catalin
    Thank you for the quick response I am using Google Chrome 21.0.1180.79 m and my OS is Windows 7 Home Premium 64-bit

  57. Would you like the web addresses to my sites that are having this issue, maybe it will work on others as long as this is the case it will be fine, just let me know.

  58. @Stephen Mills
    I’ve tried several tests, even with your version of chrome, I can’t reproduce this error, so this means it’s related to your hosting’s server or some inconsistent functionality from your own website’s code.
    Before pursuing this issue further, I’d like you to test your code/page on another server, see if you still get the error, which I’m mostly sure you won’t.
    In the meantime, yes, you can send me the URL to catalin (at) devingredients (dot) com

  59. How can I replay the new captcha after wrong code is entered and Back browser button is used, to get out from error page back to form correctly with new captcha image ?

    I suspect the session needs to be unset first, but have no idea how to correctly redisplay the captcha when back button is used after error.

  60. Can you please explain the mechanism how the new captcha is displayed in your code when you return back from error ?

    Also, I found code to generate harder to read captcha. Sometimes user can not read it correctly, and needs to redisplay a different captcha before entering it.
    How can I implement replay captcha, can you help ?

  61. BTW excellent article.

    I just thought that I would need the form and data over secure https. Any advice would be great.

  62. @Platypus

    Whenever the form is submitted the page reloads, thus a new captcha session is created with a new code. When having an error or when hitting back, the page reloads and a new captcha code is created, unless you’ve implemented it via AJAX.

    The captcha code is quite easy to understand, maybe too easy. I strongly believe that its difficulty is not a problem. In this tutorial I have not implemented a ‘refresh captcha code’ option as it defeats the purpose of a simple tutorial.

    This tutorial aims people that do not grasp a good knowledge of PHP, yet, want to take advantage of some of its capabilities. If you want more control over captcha, I’d recommend you to use an already built script for it, as it’s no point to reinvent the wheel.

    Who knows, I might try to explain a few more things about captcha in a separate tutorial.

  63. Hi there as a non php coder this tutorial is great. I had it on another server and all worked fine. When I uploaded to namesco server it says the captcha code is wrong. However if I hit the submit button again it accepts and sends . Any thoughts ? Many thx sam

  64. Hi,
    Not sure if you are still monitoring this forum, but if so would like your assistance. Haven’t done any web development work for 8 years, so totally out of the loop now. Found your site and it appears to be the easiest option for what I want. Well done.

    However as mentioned way behind the times now and having difficulty with

    a) extending the fields for name, phone email data etc, have tried adjusting in css but no luck, (purely for aesthetic purposes).

    b) tried imputing additional fields (phone) however does not appear to work for me.

    c) captcha doesnt appear to working either.

    Probably just dumb blonde syndrome, however have spent some time going over the code and no luck.
    So if you can help that would be great.

  65. @Jan
    I always monitor all articles (with the help of notifications ^^)

    It appears you also want to change the look & feel of the form, which is not something I’m covering in this tutorial.

    Adding more fields is easy, I’ve explained at the end of the tutorial, but hey, why not, archive all of your work and send it to catalin (at) devingredients (dot) com, see how we can fix your problems :)
    Besides the archive, please write in details exactly what you’re trying to achieve.

  66. Love the form. Easy to make custom and everything works. What I would like to do because I have hundreds of pages on my site is shrink the form( which can be done in the css) and then place it on each page. So is there a way to do that with out having to convert every page to php? If I have to change every extension I will have to edit all the links and it will be a mess. Thanks

  67. @Brian
    yes, just have all the PHP code in a separate file (i.e. contact_proc.php) and all the contact forms’ action’s path to contact_proc.php
    like so:
    < form action="path/to/contact_proc.php" method="post" >
    now all the processing will be done in a separate file (this is if, of course, all your contact forms have the same fields).
    Let me know how it goes.

  68. @Catalin if you email me I will share a form I had built before this with php and html to grab it. I really wanted to add captcha to it and I keep failing. I would like to see if there was a way to simply add captcha to it. Thanks

  69. Hi,
    Great tutorial you’ve got here.
    I’ve got a little issue, I keep getting the error “Your message was NOT sent
    The following error(s) returned:
    The captcha code you entered does not match. Please try again. ” when i enter the code.
    I have the session start code present and can’t seem to figure out the problem. I have sent the code to your inbox. Thanks

  70. Thanks. Great tutorial. It provided the starting point that I needed to roll up my sleeves and tackle contact forms. I’ve browsed about this subject quite a bit (the fear of a complete PHP ignoramus) and there are indeed lots of examples on the web, some of which contain solid advice; and I have to congratulate you. You offer all the basic functionality with a very clean and clear structure (a few example forms out there “die” on errors without providing the user with meaningful feedback, for instance), and you have the good-tutorial-writer-knack of making things accessible. It’s reasonably easy to add tailored complexity using your code as a template because you made it easy to understand what goes on where. I (selfishly) encourage you to write more of these things.


  71. @Germán

    Highly appreciate your feedback! I’m not sure if I’ll focus so much on back-end related articles as the main targets of this blog are front-end technologies. This PHP contact form tutorial is merely a quick solution for front-end developers who wish to be able to create often needed back-end support without a programmer at their side.
    I’m quite certain the JavaScript will be a main focus from now on, as you know, JavaScript is the future.
    But hey, you never know, I might come back to some back-end HowTos


  72. @Beth
    Simple, where you specify the e-mail address, just add more separated by commas
    $to = “”
    $to = “,,”


  73. Fantastic! so very very useful.

    However, one glitch i have noticed. the captcha. if the you enter the wrong number, it wont let it submit. but if it is blank it will. Maybe it’s just me?


  74. @Ben
    this is probably the most common mistake people make when building this contact form. The behavior you’ve explained seems to be due to not starting a new session in the contact page, if you’ll read more carefully (including most comments here), at the very top of your contact.php page you need to add:

    session_start(); // start a session

    Between the PHP tags < ?php ? >

  75. HAH disregard my last comment. I had a typo in the session start bit. I cannot thank you enough. I’m not one to simply copy code but this was a very easy introduction into PHP. Much appreciated.

    One question. should we be OK to use it in a real scenario? should we be worried about email injection and other exploits?

    Many thanks.

  76. @Ben

    Very welcome!

    You need to understand that this is a basic contact form with a very basic captcha protection, it’s ok to use it on regular websites, but I wouldn’t recommend it for websites with high-traffic volumes.

    Then again, at this very moment, a 100% secure captcha does not exist :)

  77. hey, great tutorial, really quick and easy to follow and written very well. I have built one and it works great so thank you! just a quick question though…how exactly do you add a phone number field? of the 3 pieces of code to add im fine with the first 2, i can see clearly where they go (they match areas of code already written), but where do i put the 3rd piece of code? (this seems completely different to any of the other code so im unsure where to put it) any help or advice would be greatly appreciated. Thanks again for writing this tutorial, this is the best contact form i have come across!

  78. i see where to put it now! had a total blind moment then, sorry for asking such a stupid question! great tutorial, best on the web! thank you!

  79. argh…i seem to have hit another slight problem…when i try to float the whole contact form left (so that i can put other stuff to the right of it) the layout gets all messed up and nothing is lined up anymore, i have tried wrapping the whole form in a parent div but this dose’nt help…any suggestions would be greatly appreciated, thank you

  80. @SteveThompson
    Glad you have managed in the end!
    This form has a very basic CSS on it, quite the least focus I’d say.
    I’d have to see the page layout to figure out why the form is messing up your page.

  81. thanks for getting back so quickly, i have managed to work it out. Im new to web design, this is only the 2nd site I have built, so the fact i have been able to follow your tutorial and understand it (i think lol) says a lot about the high quality of the article, thank you very much

  82. Hi Catalin

    sorry to bother you again. I have noticed that the capthca code only views in chrome on firefox just the word Captcha is shown and in opera nothing appears same for safari too. I’m a bit confused becuase the last time I checked they all worked fine.


  83. Thank you for such a comprehensive tutorial. I appreciate all the details you included.

    I’m having a few issues implementing the captcha image. I have all the code in place, but my captcha image is not showing up. The text field is there, but no captcha image.

    Also, when I start a new session, the fields are filled in with error messages. Example:
    Notice: Undefined index: name in C:\xampp\htdocs\Northfield Cabinet Shop\contact_v2.php on line 168 (This is in the name field when starting a new session). Is there a way to clear the fields when starting a new session and after the form is sent?

    Any help you’d be willing to offer would be great.
    Thanks again!

  84. @Kate

    By the looks of it, PHP can’t find an input field where a $_POST request needs it, probably you renamed one or more fields and have forgotten to also rename the $_POST requests.

    I can take a peek and see where the little problem is :)
    catalin (at) devingredients (dot) com

  85. I really enjoy this script and I constantly pass it along to others looking for a contact or feedback script.Catalin,you have made it easy to setup and offer a huge amount of suport and that initself makes this script one of the best around.I am anxiously awaiting you next project(the jquery countdown was awesome !)

  86. @bud
    Thanks a lot! You’ve also gave great feedback and support. I somehow manage to keep myself busy with some projects and I hope I’ll be able to get back to regaular posting soon

  87. Thanks a lot for the tutorial.. However, when I want to redirect the page after submission to thank you page, I get this error ” Cannot modify header information – headers already sent by ” can you help me out on this please? if you can point out where I should enter the header location code that would be great. (php newbie here!) Thanks again.

  88. Thank you very much for this very own simple captcha code. Finally this save my day. Simply modified on my newly upgraded Prestashop 1.5.3 online store.

  89. if i link directly to you captcha.php (used for preview above) i can get it to show up. i tried to download the files used for preview but it only returned the png for some good reason 😀 so i know its working. i just wanted to compare whats inside the files used for preview to what is inside the files in the zip and the code shown above. sure there must be something missing. i tried to host the files from the zip on a hosted server and on my own pc. in both cases the png does not show up. other than that its working as it should

  90. @Bo Herrmannsen

    Make sure your server has imagemagick installed. Talk to your hosting company to verify.
    You might as well mention the problem as well, since the code is fine and should work perfectly if the server is properly set.

  91. @catalin

    if i call captcha.php directly i get this:

    �PNG IHDR2���PLTE����ٟ�IIDAT�c ���o����� 7�4[�-S����glc�{�t�}�؀��F΀���m�Hk�Y�IEND�B

  92. tried to use the version without captcha… it says message sent but messeage does not show up on my gmail… not even in spam folder

  93. Haha, still haven’t fixed the “too”. Anyway, works great! Quickly made a style sheet, and I love it 😀
    This is what it looks like by the way ( Anyway, a advanced captcha tutorial would be nice to have also.

  94. Okay, I actually have another question. Is there a way to send it as a email, that has a custom FROM? Like mine are all sent from

  95. are there an “recommended” server package for win7 ? currently i use wamp but would switch to something else that works out the box with this form. only i require appache, php and mysql.

  96. got it running…. but it does not send a mail… no matter what e-mail i set nothing comes in the inbox nor spam folder

  97. thank you thank you!!

    this has made it all so very clear and after struggling with other tutorials and the recaptcha site I finally have it working correctly thanks to you.


  98. Hi, great tutorial. Got the form working brilliantly.

    I want to add additional fields to to the form for example Telephone number. I have added validation like:

    if (!empty($_POST[‘number’])) {
    $number = $_POST[‘number’];
    } else {
    $error .= “You didn’t type in your telephone number. “;

    How do I include the number into the form that gets created in this section:

    if (empty($error)) {
    $from = ‘From: ‘ . $name . ‘ ‘;
    $to = “”;
    $subject = “New email from your website.”;
    $content = $name . ” has sent you a message: \n” . $message;
    $emailMessage = “Telephone Number: ” . $number ;
    $success = “Thank you! Your message has been sent!”;

    I can’t work it out, Thank you and I appreciate any help you can give.

    Kind Regards,

  99. It would have helped if I read to the end of the tutorial before commenting. You advised how to do this at the end. Sorry.

  100. Hi Catalin,how are you doing my friend?It has been a while since my last visit.I see you are still getting a lot of trafic to this awesome tutorial.I am happy about that.I have been trying to make a slight change to the captcha script.I went through all of the comments wondering if anyone else may have asked it already.However I did not find it unless I missed it.I am trying to make the image and the number/test larger.I can make the adjustment to the image size to enlarge that part but the font is not becoming and larger.How can the font size be changed up or down?Take care my friend-Bud

    1. I went and did this the old fashioned way.I used the width & height for an image and sized it to fit my needs-lol

      1. Good to hear from you, Bud :)

        Yes, one of the solutions is to change the width and height of the image, as the code/text inside of it will stretch accordingly.

  101. Excellent tutorial, thanks to this I have gone for a much more complex solution! Works like a charm.

    Just a little note: I found it more convenient to use one form and redirect to the same php page with action=””, that way it’s usable in all scenarios. There is something possibly more up to date to date for the e-mail address validation: (!filter_var($email, FILTER_VALIDATE_EMAIL)), don’t know, someone has maybe pointed it out already, but too many comments to read. :)

    Otherwise one of the best stuff, I’ve found on the web!

      1. Catalin, please, how and where exactly should the character set be specified? I have tried to send the emaiil to different servers, Gmail’s doing fine, but another servers are showing hieroglyphs instead of UTF-8, in which my site is written. I have tried everything that I could find on the web, nothing works…

        Thanks for any help and keep up the good work!

  102. Wow, very nice and you seem to still be active (5yrs!) with inquiries. Kudos Kudos Kudos.
    I’m new to PHP and have been trying to implement a get sender ip address with:
    $serverIP = $_SERVER[“SERVER_ADDR”];
    echo “Server IP is: {$serverIP}“;

    I had it working partially, but it walked all over the primary message body.
    Any pointers would be greatly appreciated…

    1. Thanks Dennis ^_^

      Like in the examples above, we’re attaching all the information we want onto the $content variable which is sent as the email’s body.
      You could do the same, fetch any information you want and just add it in there.
      i.e. $content = $name . ” has sent you a message: \n” . $message . “\n Phone number: ” . $phone . “\n Server IP is: ” . $serverIP ;

      Hope this helped.

  103. I cannot get the form to work with captcha. When I enter the captcha and try to submit the form, it says “The captcha code you entered does not match. Please try again.”

    I’ve made sure that both the contact.php and captcha.php have on the very first line
    Any suggestion?

    1. You’ve made sure that both contact and captcha have..what on the very first line? The session_start?
      Like so? < ?php session_start(); ?>

    2. Correction “I’ve made sure that both the contact.php and captcha.php have on the very first line “.
      Any suggestion?

  104. Hey Catalin,good to see your still around and keeping busy too.I really like the way you were able to incorparate the script into boxes with color codes for things.I have just started looking at that and am impressed with how it makes your site even more cool ( if that is even possible) If you get a chance drop me an email and tell me whats up and maybe even set me up with the place you found the cool script to “colorize” your site.Or if it is home made???


    1. Hello Bud,

      Good to hear from you again :-)
      The theme is called Sparkling from:
      The code highlighter is: Crayon Syntax Highlighter

      All the best!

      1. Wow that looks really intense,alot to figure out too.I did not see any examples or demos for the code.Did you find any?

  105. Hi

    How can I make the script go to a thank you page after the form has been submitted and also if there are any errors, can the errors be displayed on a error page rather than the same page?

    1. Ian,

      I’m afraid that this is beyond the scope of this article.
      But in a few words, you’ll have to change the action to send the form data to a new page (rather than to the same page as how it is currently) and move the data handling logic over there, from there you either display errors if there are any, and/or display the thank you page.

      But I cannot go into every detail, it’s beyond this article’s scope, but shouldn’t be too difficult if you dig up some examples online + the code from this article.

      Best of luck!

  106. It will not send the form when an email uses a underscore like this one..
    .I tried it with more then one address and they all do not go through with the underscore.

    Can that be fixed or is it security thing we need to keep in there?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">