How to rate limit in WordPress API

At the moment, there is no real rate limit for the individual API endpoints. For a client, I had to limit 60 API requests per minute from an IP address. In this blog post I will explain how I did that.

By using rest_api_init, one can hook before a request is served and add logic to the rest API endpoint.

In our use case, we used that hook to build logic to count the number of requests made from an IP address. I could count that number in the options table, but I preferred using transient to cache the result in Redis. FYI If your server doesn’t use any caching tools like Redis or Memcached, then that value will be saved in the options table.

Once the limit is reached, then we reply with a 429 HTTP status code.

The complete code:

add_action('rest_api_init', function ($wp_rest_server) {
    if (!isset($_SERVER['REMOTE_ADDR'])) {
        return;
    }

    $max_limit = 60;
    $ip = sanitize_text_field($_SERVER['REMOTE_ADDR']);
    $cache_key = 'rate_limit_' . $ip;

    $cache = get_transient($cache_key);

    if (empty($cache)) {
        $cache = 0;
    }

    $cache++;

    if ($cache > $max_limit) {
        status_header(429);
        echo wp_json_encode(
            array('message' => 'Rate limit exceeded: ' . $max_limit . ' requests per minute is allowed. Please try again after a minute.')
        );
        die;
    }

    set_transient($cache_key, $cache, 60);
});

If you want to have a different logic, you can contact me or create an issue on the GitHub repository.