Title: wp_new_comment
Published: April 25, 2014
Last modified: August 20, 2026

---

# wp_new_comment( array $commentdata, bool $wp_error = false ): int|false|󠀁[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)󠁿

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#description)
    - [See also](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#see-also)
 * [Parameters](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#wp--skip-link--target)

Adds a new comment to the database.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#description)󠁿

Filters new comment to ensure that the fields are sanitized and valid before inserting
comment into database. Calls [‘comment_post’](https://developer.wordpress.org/reference/hooks/comment_post/)
action with comment ID and whether comment is approved by WordPress. Also has [‘preprocess_comment’](https://developer.wordpress.org/reference/hooks/preprocess_comment/)
filter for processing the comment data before the function handles it.

We use `REMOTE_ADDR` here directly. If you are behind a proxy, you should ensure
that it is properly set, such as in wp-config.php, for your environment.

See [https://core.trac.wordpress.org/ticket/9235](https://core.trac.wordpress.org/ticket/9235/)

### 󠀁[See also](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#see-also)󠁿

 * [wp_insert_comment()](https://developer.wordpress.org/reference/functions/wp_insert_comment/)

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#parameters)󠁿

 `$commentdata`arrayrequired

Comment data.

 * `comment_author` string
 * The name of the comment author.
 * `comment_author_email` string
 * The comment author email address.
 * `comment_author_url` string
 * The comment author URL.
 * `comment_content` string
 * The content of the comment.
 * `comment_date` string
 * The date the comment was submitted. Default is the current time.
 * `comment_date_gmt` string
 * The date the comment was submitted in the GMT timezone.
    Default is `$comment_date`
   in the GMT timezone.
 * `comment_type` string
 * Comment type. Default `'comment'`.
 * `comment_parent` int
 * The ID of this comment’s parent, if any. Default 0.
 * `comment_post_ID` int
 * The ID of the post that relates to the comment.
 * `user_id` int
 * The ID of the user who submitted the comment. Default 0.
 * `user_ID` int
 * Kept for backward-compatibility. Use `$user_id` instead.
 * `comment_agent` string
 * Comment author user agent. Default is the value of `'HTTP_USER_AGENT'` in the`
   $_SERVER` superglobal sent in the original request.
 * `comment_author_IP` string
 * Comment author IP address in IPv4 format. Default is the value of `'REMOTE_ADDR'`
   in the `$_SERVER` superglobal sent in the original request.

`$wp_error`booloptional

Should errors be returned as [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)
objects instead of executing [wp_die()](https://developer.wordpress.org/reference/functions/wp_die/)?

More Arguments from wp_die( … $args )

Arguments to control behavior. If `$args` is an integer, then it is treated as the
response code.

 * `response` int
 * The HTTP response code. Default 200 for Ajax requests, 500 otherwise.
 * `link_url` string
 * A URL to include a link to. Only works in combination with $link_text.
 * `link_text` string
 * A label for the link to include. Only works in combination with $link_url.
 * `back_link` bool
 * Whether to include a link to go back. Default false.
 * `text_direction` string
 * The text direction. This is only useful internally, when WordPress is still loading
   and the site’s locale is not set up yet. Accepts `'rtl'` and `'ltr'`.
    Default
   is the value of [is_rtl()](https://developer.wordpress.org/reference/functions/is_rtl/).
 * `charset` string
 * Character set of the HTML output. Default `'utf-8'`.
 * `code` string
 * Error code to use. Default is `'wp_die'`, or the main error code if $message 
   is a [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/).
 * `exit` bool
 * Whether to exit the process after completion. Default true.

Default:`false`

## 󠀁[Return](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#return)󠁿

 int|false|[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)
The ID of the comment on success, false or [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)
on failure.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#source)󠁿

    ```php
    function wp_new_comment( $commentdata, $wp_error = false ) {
    	global $wpdb;

    	/*
    	 * Normalize `user_ID` to `user_id`, but pass the old key
    	 * to the `preprocess_comment` filter for backward compatibility.
    	 */
    	if ( isset( $commentdata['user_ID'] ) ) {
    		$commentdata['user_ID'] = (int) $commentdata['user_ID'];
    		$commentdata['user_id'] = $commentdata['user_ID'];
    	} elseif ( isset( $commentdata['user_id'] ) ) {
    		$commentdata['user_id'] = (int) $commentdata['user_id'];
    		$commentdata['user_ID'] = $commentdata['user_id'];
    	}

    	$prefiltered_user_id = ( isset( $commentdata['user_id'] ) ) ? (int) $commentdata['user_id'] : 0;

    	if ( ! isset( $commentdata['comment_author_IP'] ) ) {
    		$commentdata['comment_author_IP'] = $_SERVER['REMOTE_ADDR'];
    	}

    	if ( ! isset( $commentdata['comment_agent'] ) ) {
    		$commentdata['comment_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
    	}

    	/**
    	 * Filters a comment's data before it is sanitized and inserted into the database.
    	 *
    	 * @since 1.5.0
    	 * @since 5.6.0 Comment data includes the `comment_agent` and `comment_author_IP` values.
    	 *
    	 * @param array $commentdata Comment data.
    	 */
    	$commentdata = apply_filters( 'preprocess_comment', $commentdata );

    	$commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID'];

    	// Normalize `user_ID` to `user_id` again, after the filter.
    	if ( isset( $commentdata['user_ID'] ) && $prefiltered_user_id !== (int) $commentdata['user_ID'] ) {
    		$commentdata['user_ID'] = (int) $commentdata['user_ID'];
    		$commentdata['user_id'] = $commentdata['user_ID'];
    	} elseif ( isset( $commentdata['user_id'] ) ) {
    		$commentdata['user_id'] = (int) $commentdata['user_id'];
    		$commentdata['user_ID'] = $commentdata['user_id'];
    	}

    	$commentdata['comment_parent'] = isset( $commentdata['comment_parent'] ) ? absint( $commentdata['comment_parent'] ) : 0;

    	$parent_status = ( $commentdata['comment_parent'] > 0 ) ? wp_get_comment_status( $commentdata['comment_parent'] ) : '';

    	$commentdata['comment_parent'] = ( 'approved' === $parent_status || 'unapproved' === $parent_status ) ? $commentdata['comment_parent'] : 0;

    	$commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '', $commentdata['comment_author_IP'] );

    	$commentdata['comment_agent'] = substr( $commentdata['comment_agent'], 0, 254 );

    	if ( empty( $commentdata['comment_date'] ) ) {
    		$commentdata['comment_date'] = current_time( 'mysql' );
    	}

    	if ( empty( $commentdata['comment_date_gmt'] ) ) {
    		$commentdata['comment_date_gmt'] = current_time( 'mysql', true );
    	}

    	if ( empty( $commentdata['comment_type'] ) ) {
    		$commentdata['comment_type'] = 'comment';
    	}

    	$commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );

    	if ( is_wp_error( $commentdata['comment_approved'] ) ) {
    		return $commentdata['comment_approved'];
    	}

    	$commentdata = wp_filter_comment( $commentdata );

    	if ( ! in_array( $commentdata['comment_approved'], array( 'trash', 'spam' ), true ) ) {
    		// Validate the comment again after filters are applied to comment data.
    		$commentdata['comment_approved'] = wp_check_comment_data( $commentdata );
    	}

    	if ( is_wp_error( $commentdata['comment_approved'] ) ) {
    		return $commentdata['comment_approved'];
    	}

    	$comment_id = wp_insert_comment( $commentdata );

    	if ( ! $comment_id ) {
    		$fields = array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content' );

    		foreach ( $fields as $field ) {
    			if ( isset( $commentdata[ $field ] ) ) {
    				$commentdata[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->comments, $field, $commentdata[ $field ] );
    			}
    		}

    		$commentdata = wp_filter_comment( $commentdata );

    		$commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );
    		if ( is_wp_error( $commentdata['comment_approved'] ) ) {
    			return $commentdata['comment_approved'];
    		}

    		$comment_id = wp_insert_comment( $commentdata );
    		if ( ! $comment_id ) {
    			return false;
    		}
    	}

    	/**
    	 * Fires immediately after a comment is inserted into the database.
    	 *
    	 * @since 1.2.0
    	 * @since 4.5.0 The `$commentdata` parameter was added.
    	 *
    	 * @param int        $comment_id       The comment ID.
    	 * @param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.
    	 * @param array      $commentdata      Comment data.
    	 */
    	do_action( 'comment_post', $comment_id, $commentdata['comment_approved'], $commentdata );

    	return $comment_id;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/comment.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.1/src/wp-includes/comment.php#L2372)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.1/src/wp-includes/comment.php#L2372-L2494)

## 󠀁[Hooks](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#hooks)󠁿

 [do_action( ‘comment_post’, int $comment_id, int|string $comment_approved, array $commentdata )](https://developer.wordpress.org/reference/hooks/comment_post/)

Fires immediately after a comment is inserted into the database.

 [apply_filters( ‘preprocess_comment’, array $commentdata )](https://developer.wordpress.org/reference/hooks/preprocess_comment/)

Filters a comment’s data before it is sanitized and inserted into the database.

## 󠀁[Related](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#related)󠁿

| Uses | Description | 
| [wp_check_comment_data()](https://developer.wordpress.org/reference/functions/wp_check_comment_data/)`wp-includes/comment.php` |

Checks whether comment data passes internal checks or has disallowed content.

  | 
| [wpdb::strip_invalid_text_for_column()](https://developer.wordpress.org/reference/classes/wpdb/strip_invalid_text_for_column/)`wp-includes/class-wpdb.php` |

Strips any invalid characters from the string for a given table and column.

  | 
| [current_time()](https://developer.wordpress.org/reference/functions/current_time/)`wp-includes/functions.php` |

Retrieves the current time based on specified type.

  | 
| [wp_get_comment_status()](https://developer.wordpress.org/reference/functions/wp_get_comment_status/)`wp-includes/comment.php` |

Retrieves the status of a comment by comment ID.

  | 
| [wp_filter_comment()](https://developer.wordpress.org/reference/functions/wp_filter_comment/)`wp-includes/comment.php` |

Filters and sanitizes comment data.

  | 
| [wp_insert_comment()](https://developer.wordpress.org/reference/functions/wp_insert_comment/)`wp-includes/comment.php` |

Inserts a comment into the database.

  | 
| [wp_allow_comment()](https://developer.wordpress.org/reference/functions/wp_allow_comment/)`wp-includes/comment.php` |

Validates whether this comment is allowed to be made.

  | 
| [absint()](https://developer.wordpress.org/reference/functions/absint/)`wp-includes/load.php` |

Converts a value to non-negative integer.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  | 
| [do_action()](https://developer.wordpress.org/reference/functions/do_action/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to an action hook.

  | 
| [is_wp_error()](https://developer.wordpress.org/reference/functions/is_wp_error/)`wp-includes/load.php` |

Checks whether the given variable is a WordPress Error.

  |

[Show 6 more](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#)

| Used by | Description | 
| [wp_handle_comment_submission()](https://developer.wordpress.org/reference/functions/wp_handle_comment_submission/)`wp-includes/comment.php` |

Handles the submission of a comment, usually posted to wp-comments-post.php via a comment form.

  | 
| [wp_ajax_replyto_comment()](https://developer.wordpress.org/reference/functions/wp_ajax_replyto_comment/)`wp-admin/includes/ajax-actions.php` |

Handles replying to a comment via AJAX.

  | 
| [wp_xmlrpc_server::pingback_ping()](https://developer.wordpress.org/reference/classes/wp_xmlrpc_server/pingback_ping/)`wp-includes/class-wp-xmlrpc-server.php` |

Retrieves a pingback and registers it.

  | 
| [wp_xmlrpc_server::wp_newComment()](https://developer.wordpress.org/reference/classes/wp_xmlrpc_server/wp_newcomment/)`wp-includes/class-wp-xmlrpc-server.php` |

Creates a new comment.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#changelog)󠁿

| Version | Description | 
| [5.5.0](https://developer.wordpress.org/reference/since/5.5.0/) | Introduced the `comment_type` argument. | 
| [4.7.0](https://developer.wordpress.org/reference/since/4.7.0/) | The `$avoid_die` parameter was added, allowing the function to return a [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/) object instead of dying. | 
| [4.3.0](https://developer.wordpress.org/reference/since/4.3.0/) | Introduced the `comment_agent` and `comment_author_IP` arguments. | 
| [1.5.0](https://developer.wordpress.org/reference/since/1.5.0/) | Introduced. |

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#user-contributed-notes)󠁿

 1.   [Skip to note 3 content](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#comment-content-1201)
 2.    [Codex](https://profiles.wordpress.org/codex/)  [  11 years ago  ](https://developer.wordpress.org/reference/functions/wp_new_comment/#comment-1201)
 3.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%23comment-1201)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%23comment-1201)
 4.  **Basic Example**
 5.      ```php
         global $post, $current_user; //for this example only :)
     
         $commentdata = array(
         	'comment_post_ID'      => $post->ID,             // To which post the comment will show up.
         	'comment_author'       => 'Another Someone',     // Fixed value - can be dynamic.
         	'comment_author_email' => 'someone@example.com', // Fixed value - can be dynamic.
         	'comment_author_url'   => 'http://example.com',  // Fixed value - can be dynamic.
         	'comment_content'      => 'Comment messsage...', // Fixed value - can be dynamic.
         	'comment_type'         => '',                    // Empty for regular comments, 'pingback' for pingbacks, 'trackback' for trackbacks.
         	'comment_parent'       => 0,                     // 0 if it's not a reply to another comment; if it's a reply, mention the parent comment ID here.
         	'user_id'              => $current_user->ID,     // Passing current user ID or any predefined as per the demand.
         );
     
         // Insert new comment and get the comment ID.
         $comment_id = wp_new_comment( $commentdata );
         ```
     
 6.   [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%3Freplytocom%3D1201%23feedback-editor-1201)
 7.   [Skip to note 4 content](https://developer.wordpress.org/reference/functions/wp_new_comment()/?output_format=md#comment-content-2140)
 8.    [rogerlos](https://profiles.wordpress.org/rogerlos/)  [  10 years ago  ](https://developer.wordpress.org/reference/functions/wp_new_comment/#comment-2140)
 9.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%23comment-2140)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%23comment-2140)
 10. **Warning:** If you set `comment_type` to one of these words:
 11. “all”, “comment”, “comments”, “pings”
 12. WordPress will save the comment with that type but you will be unable to retrieve
     it using normal WordPress comment functions. Here’s what happens to those reserved
     words inside `[WP_Comment_Query](https://developer.wordpress.org/reference/classes/wp_comment_query/)`,
     where types are gathered into `comment_type__in` whether you send them via the`
     type` or `type__in` argument:
 13.  * **all** – No `'comment_type__in'` clause will be in query
      * **comment** or **comments** – `''` added to `comment_type_in`
      * **pings** – `'pingback','trackback'` added to `comment_type_in`
 14. Because of this, you will not be able to retrieve the comment using “normal” WordPress
     functions. To get it, you will have to filter `comments_clauses` to ensure your
     type is added to the `WHERE` clause. For example, the following will replace the`''`
     inserted instead of “comment” with `'comment'`:
 15.     ```php
         add_filter( 'comments_clauses', 'add_comment_to_clauses', 10, 2 );
     
         function add_comment_to_clauses( $clauses, $WP_Comment_object ) {
     
             // use regex to find the empty string in where clause
             $clauses['where'] = preg_replace_callback(
                 "~(comment_type[ ]*IN[ ]*\\(.*)('')~i",
                 function ( $matches ) {
                     // $matches[1] was everything up to the '' 
                     // $matches[2] was the empty string
                     return $matches[1] . "'','comment'";
                 },
                 $clauses['where']
             );
     
             return $clauses;
         }
         ```
     
 16.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F%3Freplytocom%3D2140%23feedback-editor-2140)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_new_comment%2F)
before being able to contribute a note or feedback.