Considering regular WordPress ajax requests like these:

add_action( 'wp_ajax_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );
add_action( 'wp_ajax_nopriv_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );

Will it be best to end function merrychristmas_happynewyear with die(), die(0), wp_die(), or something else and why?

8 Answers 8


Using wp_die() is the best of those options.

As others have noted, there are many reasons to prefer a WordPress-specific function over the plain die or exit:

  • It allows other plugins to hook into the actions called by wp_die().
  • It allows a special handler for exiting to be used based on context (the behavior of wp_die() is tailored based on whether the request is an Ajax request or not).
  • It makes it possible to test your code.

The last one is more important, which is why I added that note to the Codex. If you want to create unit/integration tests for your code, you will not be able to test a function that calls exit or die directly. It will terminate the script, like it is supposed to. The way that WordPress's own tests are set up to avoid this (for the Ajax callbacks that it has tests for), is to hook into the actions triggered by wp_die() and throw an exception. This allows the exception to be caught within the test, and the output of the callback (if any) to be analyzed.

The only time that you would use die or exit is if you want to bypass any special handling from wp_die() and kill the execution immediately. There are some places where WordPress does this (and other places where it might use die directly just because the handling from wp_die() is not important, or nobody has attempted to create tests for a piece of code yet, so it was overlooked). Remember that this also makes your code more difficult to test, so it would generally only be used in code that isn't in a function body anyway (like WordPress does in admin-ajax.php). So if the handling from wp_die() is specifically not desired, or you are killing the script at a certain point as a precaution (like admin-ajax.php does, expecting that usually an Ajax callback will have already properly exited), then you might consider using die directly.

In terms of wp_die() vs wp_die( 0 ), which you should use depends on what is handling the response of that Ajax request on the front end. If it is expecting a particular response body, then you need to pass that message (or integer, in this case) to wp_die(). If all it is listening for is the response being successful (200 response code or whatever), then there is no need to pass anything to wp_die(). I would note, though, that ending with wp_die( 0 ) would make the response indistinguishable from the default admin-ajax.php response. So ending with 0 does not tell you whether your callback was hooked up properly and actually ran. A different message would be better.

As pointed out in other answers, you will often find wp_send_json() et al. to be helpful if you are sending a JSON response back, which is generally a good idea. This is also superior to just calling wp_die() with a code, because you can pass much more information back in a JSON object, if needed. Using wp_send_json_success() and wp_send_json_error() will also send the success/error message back in a standard format that any JS Ajax helper functions provided by WordPress will be able to understand (like wp.ajax).

TL;DR: You should probably always use wp_die(), whether in an Ajax callback or not. Even better, send information back with wp_send_json() and friends.

  • You added some good points of view. I updated the thread with my thoughts. You may comment if you like. @J.D
    – prosti
    Commented Feb 7, 2017 at 13:12
  • @prosti Thanks, I've added a paragraph on when and why you/WordPress might use die instead of wp_die().
    – J.D.
    Commented Feb 7, 2017 at 14:25
  • I appreciate your effort, however, I don't understand why WordPress core sometimes used die() and sometimes wp_die().
    – prosti
    Commented Feb 10, 2017 at 9:27
  • Thanks @prosti. As for why WordPress sometimes uses die(), in some cases it is just legacy code, or die() is being used to kill the script as a last resort when something really unexpected happened and wp_die() didn't get called. In other cases, nobody has created tests for a piece of code, and the special handling from wp_die() isn't specifically needed, so it's been overlooked.
    – J.D.
    Commented Feb 10, 2017 at 13:49

From the codex AJAX in Plugins

add_action( 'wp_ajax_my_action', 'my_action_callback' );

function my_action_callback() {
    global $wpdb; // this is how you get access to the database

    $whatever = intval( $_POST['whatever'] );

    $whatever += 10;

        echo $whatever;

    wp_die(); // this is required to terminate immediately and return a proper response

Notice the use of wp_die(), instead of die() or exit(). Most of the time you should be using wp_die() in your Ajax callback function. This provides better integration with WordPress and makes it easier to test your code.

  • the ccodex you noted is great, but WordPress core doesn't follow it. How about that?
    – prosti
    Commented Dec 25, 2016 at 17:23
  • 3
    All the wp_send_json_* functions all use wp_send_json which still calls wp_die
    – Tunji
    Commented Dec 25, 2016 at 18:27
  • But why, I am missing something in here. Have you analyzed these functions and came up with the conclusions?
    – prosti
    Commented Feb 3, 2017 at 17:02
  • 1
    do you mind to add the note about wp_send_json into the answer? Commented Feb 3, 2017 at 17:18
  • 1
    which is correct? wp_die(0) or wp_die()?
    – Anwer AR
    Commented Feb 4, 2017 at 6:01

You can also use wp_send_json() described in the Codex as send a JSON response back to an AJAX request, and die().

So, if you have to return an array, you only have end your function with wp_send_json($array_with_values);. No need to echo or die.

You also get two help helper functions wp_send_json_success() and wp_send_json_error() which adds a key named success which will be true or false respectively.

For example:

$array_val = range( 1,10 );
var_dump( wp_send_json_error( $array_val ) ); # Output: {"success":false,"data":[1,2,3,4,5,6,7,8,9,10]}
echo 'Hey there'; # Not executed because already died.
  • wp_json_encode in case of an exception may return false, what in that case?
    – prosti
    Commented Dec 25, 2016 at 17:21
  • It throws an exception if the third argument (depth) is less than 0.
    – RRikesh
    Commented Dec 26, 2016 at 6:43
  • So you believe the wp_send_json() is the best way? Why?
    – prosti
    Commented Feb 3, 2017 at 17:04
  • @prosti wp_send_json() does some stuff for us. This question also deals with wp_send_json().
    – RRikesh
    Commented Feb 4, 2017 at 12:49
  • This is exactly @RRikesh why I am asking the WP core uses that function. So why this? Is it better that way?
    – prosti
    Commented Feb 4, 2017 at 14:03

For using wordpress ajax / woo commerce ajax general syntax is as follows:

add_action( 'wp_ajax_my_action', 'my_action_callback' );
add_action( 'wp_ajax_nopriv_my_action', 'my_action_callback' );
function my_action_callback()
// your code goes here



You should use wp_die() at end of the function.Because wordpress internally uses a filter during wp_die() function.So any plugin which is working using that filter may not work if we do not include the wp_die(). Also die() and other functions are immediately kill the PHP execution without considering any wordpress function which should be consider while terminating execution.

If you are using wp_send_json() inside you function like this

       function my_action_callback()
    // your code goes here


    //wp_die(); not necessary to use wp_die();


Its not necessary to use wp_die() at the end if you include wp_send_json() inside callback function. because wordpress itself use wp_die() function safely inside wp_send_json() function.


This is just in addition to what others said. The reason to prefer wp_die is that core can trigger actions there and plugins can properly complete things like tracing, monitoring, or caching.

In general you should always prefer a core API call over if one available as it is most likely adding some value (caching, plugin integration or whatever) which you don't get from the direct PHP call.


I will not accept this answer, this would not be fair. I just wanted to create an outline and possible hints on the items I find important:

The main definition of wp-die()

File: wp-includes/functions.php
2607: /**
2608:  * Kill WordPress execution and display HTML message with error message.
2609:  *
2610:  * This function complements the `die()` PHP function. The difference is that
2611:  * HTML will be displayed to the user. It is recommended to use this function
2612:  * only when the execution should not continue any further. It is not recommended
2613:  * to call this function very often, and try to handle as many errors as possible
2614:  * silently or more gracefully.
2615:  *
2616:  * As a shorthand, the desired HTTP response code may be passed as an integer to
2617:  * the `$title` parameter (the default title would apply) or the `$args` parameter.
2618:  *
2619:  * @since 2.0.4
2620:  * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept
2621:  *              an integer to be used as the response code.
2622:  *
2623:  * @param string|WP_Error  $message Optional. Error message. If this is a WP_Error object,
2624:  *                                  and not an Ajax or XML-RPC request, the error's messages are used.
2625:  *                                  Default empty.
2626:  * @param string|int       $title   Optional. Error title. If `$message` is a `WP_Error` object,
2627:  *                                  error data with the key 'title' may be used to specify the title.
2628:  *                                  If `$title` is an integer, then it is treated as the response
2629:  *                                  code. Default empty.
2630:  * @param string|array|int $args {
2631:  *     Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
2632:  *     as the response code. Default empty array.
2633:  *
2634:  *     @type int    $response       The HTTP response code. Default 200 for Ajax requests, 500 otherwise.
2635:  *     @type bool   $back_link      Whether to include a link to go back. Default false.
2636:  *     @type string $text_direction The text direction. This is only useful internally, when WordPress
2637:  *                                  is still loading and the site's locale is not set up yet. Accepts 'rtl'.
2638:  *                                  Default is the value of is_rtl().
2639:  * }
2640:  */
2641: function wp_die( $message = '', $title = '', $args = array() ) {
2643:   if ( is_int( $args ) ) {
2644:       $args = array( 'response' => $args );
2645:   } elseif ( is_int( $title ) ) {
2646:       $args  = array( 'response' => $title );
2647:       $title = '';
2648:   }
2650:   if ( wp_doing_ajax() ) {
2651:       /**
2652:        * Filters the callback for killing WordPress execution for Ajax requests.
2653:        *
2654:        * @since 3.4.0
2655:        *
2656:        * @param callable $function Callback function name.
2657:        */
2658:       $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2659:   } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
2660:       /**
2661:        * Filters the callback for killing WordPress execution for XML-RPC requests.
2662:        *
2663:        * @since 3.4.0
2664:        *
2665:        * @param callable $function Callback function name.
2666:        */
2667:       $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2668:   } else {
2669:       /**
2670:        * Filters the callback for killing WordPress execution for all non-Ajax, non-XML-RPC requests.
2671:        *
2672:        * @since 3.0.0
2673:        *
2674:        * @param callable $function Callback function name.
2675:        */
2676:       $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
2677:   }
2679:   call_user_func( $function, $message, $title, $args );
2680: }


File: wp-includes/functions.php
3144: /**
3145:  * Send a JSON response back to an Ajax request.
3146:  *
3147:  * @since 3.5.0
3148:  * @since 4.7.0 The `$status_code` parameter was added.
3149:  *
3150:  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
3151:  *                           then print and die.
3152:  * @param int   $status_code The HTTP status code to output.
3153:  */
3154: function wp_send_json( $response, $status_code = null ) {
3155:   @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
3156:   if ( null !== $status_code ) {
3157:       status_header( $status_code );
3158:   }
3159:   echo wp_json_encode( $response );
3161:   if ( wp_doing_ajax() ) {
3162:       wp_die( '', '', array(
3163:           'response' => null,
3164:       ) );
3165:   } else {
3166:       die;
3167:   }
3168: }


File: wp-includes/load.php
1044: /**
1045:  * Determines whether the current request is a WordPress Ajax request.
1046:  *
1047:  * @since 4.7.0
1048:  *
1049:  * @return bool True if it's a WordPress Ajax request, false otherwise.
1050:  */
1051: function wp_doing_ajax() {
1052:   /**
1053:    * Filters whether the current request is a WordPress Ajax request.
1054:    *
1055:    * @since 4.7.0
1056:    *
1057:    * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request.
1058:    */
1059:   return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
1060: }

Typically what we get from ajax call is some kind of the response. The response may be encoded in json or may not be encoded in json.

In case we need json outupt wp_send_json or two satelites are great idea.

However, we may return x-www-form-urlencoded or multipart/form-data or text/xml or any other encoding type. In that case we don't use wp_send_json.

We may return the whole html and in that case it has sense to use wp_die() first and second parameter, else these parameters should be empty.

 wp_die( '', '', array(
      'response' => null,
 ) );

But what is a benefit of calling wp_die() without parameters?

Finaly, if you check the great WP core you may find

File: wp-includes/class-wp-ajax-response.php
139:    /**
140:     * Display XML formatted responses.
141:     *
142:     * Sets the content type header to text/xml.
143:     *
144:     * @since 2.1.0
145:     */
146:    public function send() {
147:        header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) );
148:        echo "<?xml version='1.0' encoding='" . get_option( 'blog_charset' ) . "' standalone='yes'?><wp_ajax>";
149:        foreach ( (array) $this->responses as $response )
150:            echo $response;
151:        echo '</wp_ajax>';
152:        if ( wp_doing_ajax() )
153:            wp_die();
154:        else
155:            die();

Both formats are used die() and wp_die(). Can you explain why?

Finally here is what admin-ajax.php returns die( '0' );

Why not wp_die(...)?


Use wp_die(). It is better to use WordPress functions as much as you can.


If you use echo, it will force you to use die() or die(0) or wp_die().

If you don’t use echo, JavaScript can handle that.

Then you should use a better way to return data: wp_send_json().

To send data in your callback (in json format), you can use followings:




All of them will die for you. No need to exit or die afterwards.


And if you don't need json as output format, you should use:


It will return your response before it dies. As per the codex:

The function wp_die() is designed to give output just before it dies to avoid empty or time-outing responses.

Please read full codex article here.

  • 1
    Thanks, what do you suggest instead of echo?
    – prosti
    Commented Feb 9, 2017 at 15:12
  • 1
    To note, Javascript doesn't handle echo. wp_send_json_* uses echo and exits for you. There is confusion here between the client and server. Commented Feb 9, 2017 at 15:58
  • @prosti wp_send_json() Commented Feb 9, 2017 at 16:43
  • Thanks, and in case we don't need json as output format?
    – prosti
    Commented Feb 9, 2017 at 16:46
  • 1
    @prosti than you should use wp_die($response) because as per the codex: The function wp_die() is designed to give output just before it dies to avoid empty or time-outing responses. Commented Feb 9, 2017 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.