Skip to the content...

Welcome to the David Walsh Blog. I'm a MooTools, Dojo, jQuery, CSS, and PHP Web Developer located in Madison, Wisconsin, United States. Please contact me if I can make your experience on my website better.

Detect an AJAX Request in PHP

30 Responses »

I like using the same PHP script for both AJAX and non-AJAX content requests. Using one script just makes everything easier because it's only one file to update/edit and it's one more cache-able request. One way to try detect an AJAX request (as opposed to a regular page load) is by using the following PHP code:

/* decide what the content should be up here .... */
$content = get_content(); //generic function;

/* AJAX check  */
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
	/* special ajax here */
	die($content);
}

/* not ajax, do more.... */

$_SERVER['HTTP_X_REQUESTED_WITH'] is the golden ticket but not all servers provide this variable so having other checks in place will be important.

Discussion

  1. July 27, 2009 @ 9:18 am

    Wow this is going to be very very helpful…thanks, I didn’t know about this…

  2. fabian
    July 27, 2009 @ 9:25 am

    HTTP_X_REQUESTED_WITH is only sent by jQuery, isn’t it?

  3. fabian
    July 27, 2009 @ 9:26 am

    Gosh, David! Your commenting system sucks. Can’t even post the NAME of the var (without dollar sign and stuff…). Anyway, this is just set by jQuery, isn’t it?

  4. July 27, 2009 @ 9:32 am

    All of the javascript frameworks send that header.

  5. July 27, 2009 @ 10:03 am

    Yeah I felt really dumb when I found about this one a few month ago. All this time I had been using javascript to add an extra parameter to queries which I would test for on the server side. Still works, but not nearly as simple as this one

  6. puznik
    July 27, 2009 @ 10:14 am

    HTTP_X_REQUESTED_WITH is sent by ALL recent browsers supporting ajax requests ;)
    it’s the comment field used to check is request is standard or xhttprequest

  7. dev words
    July 27, 2009 @ 10:56 am

    Is this guarenteed to work. The frameworks may all send it but can you get round it with raw javascript.

  8. July 27, 2009 @ 11:43 am

    I don’t think it has anything to do with frameworks. it’s just sent with any ajax request generated by the browser

  9. July 27, 2009 @ 1:42 pm

    I know dojo doesn’t sends it (but I could be wrong)

    You will have to do something like this to work in dojo:

    dojo.xhrGet({
    url: “some/file.cgi”,
    headers: {
    “X-Requested-With”: “whatever”
    }
    });

  10. July 27, 2009 @ 10:21 pm

    Very nice post, thanks for sharing! I’m a huge fan of the blog, really like the design and you’ve got some great content on here. If you’d be interested, I’d love to have an interview with you on my web 2.0 blog. Just let me know if you’re interested – http://www.insidethewebb.com/

  11. July 28, 2009 @ 5:11 am

    yeah! nice!

  12. July 28, 2009 @ 7:21 am

    Freak !
    By this way, nobody can get some data :)
    Thanks a lot, I’ll test after !

  13. simon
    July 28, 2009 @ 11:52 am

    Very nice ! I didn’t know about this. That’s going to be very helpfull !
    Just a question about your if statement. I never understood why people made double checks like this one:
    if(!empty($var) && $var == “Hello World”)
    Why not just check it like this:
    if($var == “Hello World”)
    Isn’t it exactly the same, or even better for performance ?
    Thanks and again, great article !

  14. July 28, 2009 @ 11:53 am

    @Simon: Because “$var” may not be “set” so not checking for that would throw a PHP notice.

  15. simon
    July 28, 2009 @ 12:20 pm

    ok… Shame on me… xD
    It has become a reflex to use if(isset()), I guess that’s why I forgot why it was necessary ;)

  16. July 29, 2009 @ 1:36 pm

    So if you’re using this do you think its time to stop supporting people with javascript turned off? I still see lots of people supporting it.

  17. July 30, 2009 @ 3:08 am

    @Dev Words: yes, stop if you want to leave Google out of the door. :)
    However, it seems that Dojo sends this header since Zend Framework components check for X-Requested-With and dojo has a out-of-the-box integration with ZF.

  18. August 2, 2009 @ 5:58 pm

    Be careful when using the same URL for AJAX and non-AJAX requests. This could cause some strange behavior at a proxy cache on the client’s network.

    Imagine if a proxy cache were to cache your AJAX response when one user was interacting with your application, and then another user behind the same proxy cache goes to access your application. He’ll see the AJAX response instead of the markup for your application.

    You can discourage caching by sending the appropriate cache control headers, but I’ve seen proxy caches that seem to ignore these directives, so you might get some undesired caching anyway…

  19. August 6, 2009 @ 2:28 pm

    This is a good idea to implement, but isn’t something i would rely when it comes to security. Remember that client headers can be faked to look like something else. However this is just one more thing to kink the system when being attacked.

  20. syaz
    August 14, 2009 @ 11:42 pm

    Like Jonathan Yarbor said. Only use this for user-friendliness, never use it for security purposes as everything sent by client can be faked easily nowadays.

  21. sébastien hutter
    August 20, 2009 @ 10:53 am

    Looks like jQuery doesn’t send back HTTP_X_REQUESTED_WITH on 302 redirections (eg : php function header(‘Location: page.php’) ) occuring on $.load() calls. So be carefull with automatic redirections in your code…

    Does anyone knows a way to forward HTTP_X_REQUESTED_WITH even through redirections ?

  22. vijay
    September 2, 2009 @ 10:08 am

    Wow Nice Example This is very help ful for me Thanks

  23. October 26, 2009 @ 10:03 am

    Just to clear up any confusion:
    Yes, the header IS added by frameworks; e.g. jQuery has this line:
    xhr.setRequestHeader(“X-Requested-With”,”XMLHttpRequest”);
    The mini-framework I use didn’t send that header; I had to put it in myself.

  24. housni
    November 12, 2009 @ 11:02 am

    The condition would fail under IE7.
    It appears that IE7 doesn’t recognize the header.
    IE needs to say hello to the 21st century :)

  25. November 12, 2009 @ 11:45 am

    @Housni: IE was the first browser to introduce ajax to the masses.

  26. housni
    November 12, 2009 @ 11:51 am

    @Ben: That maybe so but unfortunately, they seem to stick to their own standards which leads to bad practice such as CSS hacks for example.
    It seems as though IE7 not recognizing the header may be cache related.
    I need to investigate this more.

  27. scvinodkumar
    January 13, 2010 @ 8:02 am

    $_SERVER['HTTP_X_REQUESTED_WITH'] is empty. How to enable this variable in server?

  28. January 22, 2010 @ 7:52 pm

    @scvinodkumar, like 10 other people before me i’ll say that this header is sent by the javascript framework with which you’re making the ajax call. You can’t ‘enable’ it in your server, the js framework does…

  29. February 13, 2010 @ 9:01 am

    That’s awesome.
    Just used it on a website I’m making at the moment (mine) Works great with Drupal templates.

  30. reid
    February 26, 2010 @ 1:14 pm

    @Fabian: Gosh, Fabian! You’re a d-bag, aren’t you?

Be Heard!

Share your thoughts with fellow developers of all skill levels! I want to hear from you!

Name*:
Email*:
Website:  
Wrap your code with <code> tags, f00!