tetchi blog

Tetchi's blog about life and stuff

How to post comments using the WordPress REST API

A quick tutorial on how to use the WordPress REST API to post comments asynchronously.

I recently converted my WordPress blog into a headless, Gatsby-powered site, and one of my requirements was to have a working comment form. I knew this was possible using the WordPress REST API but I didn’t find the documentation very helpful and was not able to find any good examples. I decided to document the steps I took to make a working comment form for my blog with the hopes of helping others looking to do a similar thing.

The example in this post uses React JSX, but the code can easily be applied to a regular PHP-based WordPress site that uses vanilla JavaScript.

You can see a quick video of the comment form in action below. Or, you can also try it out by using the comment form at the bottom of this page 😊.

Posting a comment asynchronously with the WordPress REST API.

1. Open Inspector’s Network tab

First thing’s first, let’s open up Chrome’s Network tab for debugging. This handy tab will tell us if the comment was submitted properly and about any errors we might get. Other browsers should have a similar tab, but for the purpose of this tutorial I’m going to stick with Chrome.

2. Enable anonymous comments

Before we create the form, we have to enable anonymous comments on your WordPress theme. This is done by enabling the
rest_allow_anonymous_comments hook.

Open your WordPress theme’s functions.php, and add the following snippet:

  add_filter( 'rest_allow_anonymous_comments', '__return_true' );

If you skip this step and try to post a comment using the REST API, you will get a 401: Sorry, you must be logged in to comment. error.

Shoutout to @websupporter for this tip!

3. Create a form

The next step is to create the comment form. Since I’m using Gatsby, the code example below is in React JSX, but you can convert it to be plain old HTML.

  <input type="hidden" id="postId" value={POST_ID} />
    <label htmlFor="name">Name*</label>
    <input id="name" type="text" required />
    <label htmlFor="email">Email*</label>
    <label htmlFor="comment">Comment*</label>
  <input type="submit" value="Post comment!" />

The form must contain the following information:

  • post ID (usually a four digit number, ex: 4583)
  • comment author’s name
  • comment author’s email
  • content for the comment

In my case, I’m passing the post ID as a prop from my template that handles all of the GraphQL queries. If you’re working in PHP, I believe you can use <?php the_ID(); ?> to get the post ID.

Other details such as the date and IP address are filled out automatically so you shouldn’t need to pass those into the form. For the IP address, you’ll see something like ::1 on your local WordPress instance, but on your production site you should see the actual IP address of the comment author.

4. Create a handler for your form

Add an onSubmit handler to the <form>.

<form onSubmit={this.handleSubmit.bind(this)}>
  <input type="hidden" id="postId" value={POST_ID} />
    <label htmlFor="name">Name*</label>
    <input id="name" type="text" required />

Finally, let’s add the code for the handler.

handleSubmit(evt) {

  const [postId, name, email, comment] = evt.target.elements;

  const data = JSON.stringify({
    post: postId.value,
    author_name: name.value,
    author_email: email.value,
    content: comment.value,
  // ACTION_URL = "https://your-wordpress-site.com/wp-json/wp/v2/comments"
  fetch(ACTION_URL, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
    body: data,
    .then((response) => {
      if (response.ok === true) {
        // Submitted successfully!

      return response.json();
    .then((object) => {
      // Comment submission failed.
      // Output `object.message` to see the error message.
    .catch(error => console.error('Error:', error));

Here’s a quick breakdown of what’s happening:

  1. Do preventDefault() to prevent the form from submitting
  2. De-structure postId, name, email, and comment from event.target.elements
  3. Do a fetch to post to ACTION_URL (this is the /wp-json/wp/v2/comments endpoint of your WordPress blog).
  4. Once we receive the response, check for the value of response.ok.
    1. If true, the comment was submitted successfully. Otherwise, run response.json(), which returns a promise.
  5. Once the promise is resolved, we receive an object which gives us all sorts of details about what went wrong. You can output object.message to see the message that was returned from WordPress.

That’s it! You should now have a working, basic WordPress comment form that posts comments using the REST API. You can check out the code for the more complete version (including states for buttons, error messages, etc.) here – it may be useful to see it in a React/Gatsby context.

Please leave a comment if you have any questions or advice!


  • test
    test on June 24th, 2019

    test comment

  • Testing
    Testing on August 13th, 2019

    Testing Comment

  • Hanna Haritha valli
    Hanna Haritha valli on August 20th, 2019


  • Lyubo
    Lyubo on November 23rd, 2019

    How to validate the input?

  • Igor
    Igor on December 30th, 2019

    Its working?

  • abtin
    abtin on March 28th, 2020

    how can I send comment meta data with this method?using meta object doesn’t work

  • tetchi
    tetchi on March 30th, 2020

    Hi Abtin, I haven’t tried this with comment metadata at all but I’ll try to look into it in the future.

  • Ziyaho
    Ziyaho on April 5th, 2020

    Thanks for the tutorial! Just wondering, as I am trying to make my own WordPress to React app… how would you make sure users can add POSTS?

    And how would we show the CURRENT comments that are already on the website, in the app?

    Can you help?

  • Bakhtiar
    Bakhtiar on May 13th, 2020

    Thankyou worked it

  • Jonas Merhej
    Jonas Merhej on May 17th, 2020

    @Lyubo You can create a php class and make the request got through this class, and finally make the class send the request for you

  • Jins
    Jins on May 28th, 2020

    Thank you , its working fine for me

  • Bill Sing
    Bill Sing on May 29th, 2020

    Comment test

  • qweqweqwe
    qweqweqwe on June 22nd, 2020

    test comment

  • Hello
    Hello on August 23rd, 2020

    test :D

  • Hello
    Hello on September 7th, 2020

    Test comment

  • myself
    myself on October 15th, 2020

    Test Comment

  • teste
    teste on October 16th, 2020

    this is a comment

  • Mr. Trump
    Mr. Trump on October 18th, 2020

    I am really really really really well educated and really really really reach and all women love me!

  • black default skin
    black default skin on November 15th, 2020

    Headhunter a female with black hair and the model for skins like Snorkel Ops; Spitfire the black male in Fortnite and the model for the Stratus skin

  • Test
    Test on December 3rd, 2020

    Test Comment

  • Wudoka
    Wudoka on December 3rd, 2020

    Thanks! Good tutorial

  • Matty
    Matty on December 15th, 2020

    This sounds cool!

  • Bogdan
    Bogdan on December 19th, 2020

    Thank you for the tutorial !

  • Mia
    Mia on January 2nd, 2021

    Thank you so much for this! I looked all over to resolve the 401 error. This worked like a charm!

  • Pranav
    Pranav on February 19th, 2021

    Test comment

  • Chintan
    Chintan on March 5th, 2021


  • kaz
    kaz on August 13th, 2021

    test comment

    MARKETING AGENCY on August 25th, 2021

    We are using this solution – thanks!

  • mouad achemli
    mouad achemli on September 16th, 2021

    nice job, missing parent comment id, im using in my case

    parent: $(‘#comment_parent’).val()

  • Hari
    Hari on September 24th, 2021

    Hi, nice tutorial :) i am looking for someone who can make a gatsby & wp site for me. could you DM over Twitter or send me an email.

  • Hari
    Hari on September 24th, 2021

    test 2

  • DevAB
    DevAB on September 26th, 2021

    Thanks for the awesome tutorial.

  • TEST
    TEST on September 28th, 2021


  • TEST
    TEST on September 28th, 2021


Post a comment