ExpressionEngine 2.8.1 always gives 403 Forbidden error when using ajax. Every ajax call given "This form has expired. Please refresh and try again." response.

I have also tried to pass hidden XID

<input type="hidden" name="XID" value="{XID_HASH}" />

and made secure form's value 'n' in config file.

Anybody have solution, how can i fix it


2 Answers 2


ExpressionEngine has a protection against Cross-site Request Forgery - CSRF and a documentation available here. You just have to add that line to your form:

<input type="hidden" name="csrf_token" value="{csrf_token}">

And send the data in your AJAX request. I had the same problem today and that fixed it for me.

  • Thank you for replied. i have added <input type="hidden" name="csrf_token" value="{csrf_token}">, but still given same error, i'm not using any form, i'm using simple ajax with calendar. Apr 17, 2014 at 6:29
  • Can you make sure that the csrf_token is send in your ajax? Maybe your script doesn't grab it before sending it.
    – Romain
    Apr 17, 2014 at 19:24
  • Did yo u ever find a resolution to this? I have tried both static php files and php-enabled templates and get a 403 on both. Nov 9, 2014 at 4:04

I wouldn't recommend this but in cases where you have no choice, e.g. you cannot tweak the code in an app in time or something to that effect, you can opt to conditionally disable secure forms in your config.php or bootstrap.


// Make an exception to make AJAX forms app-compatible
// EE 2.7.x introduced mandatory XIDs even for AJAX, but an app won't have an initial valid XID to begin with
if (substr($_SERVER['REQUEST_URI'], 0, 13) == '/app/post/url')
  //$config['secure_forms'] = 'n'; // Deprecated and obsolete in EE 2.8
  $config['disable_csrf_protection'] = 'y'; // Introduced in EE 2.8, XID replaced by csrf_token

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.