Detecting Browser Autofill

217,542

Solution 1

The problem is autofill is handled differently by different browsers. Some dispatch the change event, some don't. So it is almost impossible to hook onto an event which is triggered when browser autocompletes an input field.

  • Change event trigger for different browsers:

    • For username/password fields:

      1. Firefox 4, IE 7, and IE 8 don't dispatch the change event.
      2. Safari 5 and Chrome 9 do dispatch the change event.
    • For other form fields:

      1. IE 7 and IE 8 don't dispatch the change event.
      2. Firefox 4 does dispatch the change change event when users select a value from a list of suggestions and tab out of the field.
      3. Chrome 9 does not dispatch the change event.
      4. Safari 5 does dispatch the change event.

You best options are to either disable autocomplete for a form using autocomplete="off" in your form or poll at regular interval to see if its filled.

For your question on whether it is filled on or before document.ready again it varies from browser to browser and even version to version. For username/password fields only when you select a username password field is filled. So altogether you would have a very messy code if you try to attach to any event.

You can have a good read on this HERE

Solution 2

Solution for WebKit browsers

From the MDN docs for the :-webkit-autofill CSS pseudo-class:

The :-webkit-autofill CSS pseudo-class matches when an element has its value autofilled by the browser

We can define a void transition css rule on the desired <input> element once it is :-webkit-autofilled. JS will then be able to hook onto the animationstart event.

Credits to the Klarna UI team. See their nice implementation here:

Solution 3

This works for me in the latest Firefox, Chrome, and Edge:

$('#email').on('blur input', function() {
    ....
});

Solution 4

I was reading a lot about this issue and wanted to provide a very quick workaround that helped me.

let style = window.getComputedStyle(document.getElementById('email'))
  if (style && style.backgroundColor !== inputBackgroundNormalState) {
    this.inputAutofilledByBrowser = true
  }

where inputBackgroundNormalState for my template is 'rgb(255, 255, 255)'.

So basically when browsers apply autocomplete they tend to indicate that the input is autofilled by applying a different (annoying) yellow color on the input.

Edit : this works for every browser

Solution 5

For google chrome autocomplete, this worked for me:

if ($("#textbox").is(":-webkit-autofill")) 
{    
    // the value in the input field of the form was filled in with google chrome autocomplete
}
Share:
217,542

Related videos on Youtube

Undefined
Author by

Undefined

Web Applications Developer. Likes JavaScript and Front End MVC frameworks

Updated on August 05, 2022

Comments

  • Undefined
    Undefined almost 2 years

    How do you tell if a browser has auto filled a text-box? Especially with username & password boxes that autofill around page load.

    My first question is when does this occur in the page load sequence? Is it before or after document.ready?

    Secondly how can I use logic to find out if this occurred? Its not that i want to stop this from occurring, just hook into the event. Preferably something like this:

    if (autoFilled == true) {
    
    } else {
    
    }
    

    If possible I would love to see a jsfiddle showing your answer.

    Possible duplicates

    DOM event for browser password autofill?

    Browser Autofill and Javascript triggered events

    --Both these questions don't really explain what events are triggered, they just continuously recheck the text-box (not good for performance!).

    • Esailija
      Esailija almost 12 years
      The checking takes some microseconds whereas the interval would be firing the check every 100 milliseconds or so... how is that gonna affect performance at all? If there existed an event fired by the browser I'm sure they would have used it.
    • Undefined
      Undefined almost 12 years
      I see what you mean, but it depends on the first part of my question whether JavaScript is even aware a change has just taken place (e.g. before document.ready)
    • ChrisN
      ChrisN almost 9 years
      THE BEST solution for Chrome / WebKit is to use the DOM selector: document.querySelectorAll('input:-webkit-autofill'); after a short delay setTimeout(... code here... 250);
    • Muhammad Umer
      Muhammad Umer over 7 years
      basically i want to auto login user if it's autofilled, mad annoying ot log back in when it automatically logs out.
    • Soron
      Soron about 6 years
      @ChrisN Your comment is what actually got me a (simple) solution. I don't see it as an answer, though! Post it as one and ping me, so I can upvote it in thanks.
    • orrd
      orrd over 4 years
      Why would you need to know if autofill was used? Autofill should be transparent to the website so websites shouldn't behave differently if autofill is used. The response should be the same as if the user entered the info themselves.
  • Robbert
    Robbert almost 11 years
    Please note there's a difference between autocomplete and autofill. OP is specifically referring to browsers filling in saved login details on page load.
  • Bryce
    Bryce over 10 years
    A usual hack is a mousenter on some important part of the page. The event gets triggered as the user's mouse heads for the button or some such.
  • Chris Bloom
    Chris Bloom almost 10 years
    This worked great with jQuery Custom Forms. I just dropped it in and my custom select lists worked great with autofill.
  • JakeJ
    JakeJ almost 10 years
    @Bryce Personally I would go with a 'blur' event due to the autofill being something that happens after you would enter the input area. Obviously it's not ideal but as a fallback for the browsers listed above it can be very helpful
  • T.J. Crowder
    T.J. Crowder over 9 years
    Don't forget the input event. That's what Chrome fires on autocomplete (and probably autofill as well, if Chrome has that; I always turn this stuff off).
  • Rid Iculous
    Rid Iculous about 9 years
    Perfect. The first solution I found working with Chrome!
  • Camilo Martin
    Camilo Martin about 9 years
    It's really @RidIculous how simple some solutions can be.
  • VishwaKumar
    VishwaKumar almost 9 years
    For some reason for me, this code is not working on page redirect (when i logout of application and get redirected to login page where autofill happens). Although it does work on page refresh.
  • Bridget Arrington
    Bridget Arrington almost 9 years
    @ChrisN I did test my solution with IE, browsers handle the javascsript events differently. My solution is simple and easy to read and is for one of the more difficult browsers to code for.
  • Hemant_Negi
    Hemant_Negi almost 9 years
    But elem.val() returns empty string for autofilled password fields in chrome :(
  • Camilo Martin
    Camilo Martin almost 9 years
    @Hemant_Negi Doesn't Chrome dispatch the change event anyway? Correct me if I'm wrong. I'm using LastPass and am too lazy to disable it to see if it also works without.
  • Hemant_Negi
    Hemant_Negi almost 9 years
    Yes chrome dispatch change event but, when i try to retrieve the value it returns empty.
  • Camilo Martin
    Camilo Martin almost 9 years
    @Hemant_Negi You can't get the password through scripting, as a security measure (against userscripts and XSS I assume). but you can clear it (elem.val('')), and see that it's changed with the change event. If you need to see the sumbitted password, why not use a POST form?
  • Hemant_Negi
    Hemant_Negi almost 9 years
    @CamiloMartin i know i can do that but my situation is different. im trying to make this kind of input boxes dribbble.com/shots/…. but for login form chrome autofills the username and password which my javascript can not detect and hence result in a broken ui :(
  • Camilo Martin
    Camilo Martin almost 9 years
    @Hemant_Negi I'm not sure if I understood what part are you stuck on, but here's an idea: use the input pattern attribute, and the :valid pseudo-selector so that you can implement as much as possible in CSS only.
  • MBaas
    MBaas over 8 years
    I just had to plug this little code into my $(document)-ready-fn and it all worked - THANK YOU VERY MUCH, that is useful stuff! :-)
  • Hector
    Hector over 8 years
    This code works great for me if you update the third line to ($("#inputID:-webkit-autofill").val().length > 0) {
  • Chase
    Chase over 8 years
    I haven't been able to get this to work, which very well may be my fault since I'm a JS novice, but the :valid pseudo selector isn't a solution, because it will trigger on a blank field regardless of whether or not there's a pattern. A blank field is blank, not invalid, and therefore considered valid. The only way to force an invalid state is to set the field to required, which is often the case in the common login use-cases, but there are many other form uses where using required isn't viable.
  • Camilo Martin
    Camilo Martin over 8 years
    @Chase Maybe you can restrict it further with classes. Like, select .some-class:valid?
  • Chase
    Chase over 8 years
    That would indeed specify which input, but still not whether or not it truly has a value. Unless the input is set to required, the :valid pseudo selector still won't help, because a blank input is still considered valid. The issue is auto-filled inputs technically have no value, as far as I can tell in my testing. I think this has to do with the value being loaded into the user-agent Shadow DOM when the page is loaded, with no detectable change to the input itself. But I'm not qualified.... This link has more info avernet.blogspot.in/2010/11/…
  • Camilo Martin
    Camilo Martin over 8 years
    @Chase It just occurred to me, are you running the code in my answer on document ready? Alternatively, are the forms generated by Javascript? Another option: toggling a class when input is empty/not empty.
  • Paulo Cheque
    Paulo Cheque about 8 years
    I end up with the same solution: blur event. I apply the same function for the change and blur event and it worked great. A simple solution without extra libraries.
  • ThdK
    ThdK almost 8 years
    See my one line answer if you just want to know if the value in the textbox was filled in by google chrome autocomplete.
  • GreenRaccoon23
    GreenRaccoon23 almost 8 years
    'input'! This was the easiest solution for me, but I tested for autocomplete only, not autofill.
  • pathfinder
    pathfinder over 7 years
    blur does not work for me with some auto complete add-ons
  • Braden Rockwell Napier
    Braden Rockwell Napier almost 7 years
    this is, by far, the best solution! Kudos to Lev here for this. Thanks for sharing Klarna UI's solution... nothing else has worked for me until I found this. Life Saver!
  • RiZKiT
    RiZKiT over 6 years
    Input will trigger on every keypress. If you do a server call, it may trigger to often.
  • user1069816
    user1069816 over 6 years
    As well as the CSS rules the keyframes here github.com/klarna/ui/blob/v4.10.0/Field/styles.scss#L181-L18‌​9 are also needed
  • Stefan Fisk
    Stefan Fisk over 6 years
    that looks like quite the mobile battery drainer :/
  • LcSalazar
    LcSalazar over 6 years
    @StefanFisk - Not really it doesn't. A simple repeating timer set at the JS level of a browser page is not enough to impact on your battery, as there is so much going on in most web pages.... You really think google.com sets no recurrent timers? What a power management flaw it would be if I could program simply with JS a web page that drains a user's battery....
  • perozzo
    perozzo almost 6 years
    It worked for me as well. I tried hundreds of solutions and no one worked. Thank you very much, save my day and all the times I searched for a solution.
  • pritesh
    pritesh almost 6 years
    This worked flawless for me! Needs to play around with it a little to figure out the exact approach. Thank you Klarna team
  • Petr Hladík
    Petr Hladík almost 6 years
    Great solution! This events combination solves problem with fill by user and autofill by browser.
  • ton
    ton over 5 years
    An explanation for your solution would help
  • Romick
    Romick over 5 years
    I thought it was obviously. So basically idea is to check value of the input field couple times. In current implementation it is 10 times with 100 ms delay. So when during a second 10*1000=1sec browser fill the autofill value then the callback passed to autofill will be called. In current example it just adds a class. If you have more questions please do not hesitate and just ask :).
  • anvita surapaneni
    anvita surapaneni over 5 years
    this approach trows error: "Syntax error, unrecognized expression: unsupported pseudo: -webkit-autofill" on other browsers(I tried on Firefox)
  • Ben Racicot
    Ben Racicot about 5 years
    This is the up-to-date answer.
  • rustyshackleford
    rustyshackleford about 5 years
    This is helpful.
  • moto
    moto over 4 years
    Great thinking!
  • Marcus Crisostomo
    Marcus Crisostomo over 4 years
  • Marcus Crisostomo
    Marcus Crisostomo over 4 years
    I tried this solution and worked very well for me. Thank you very much.
  • Leo
    Leo about 4 years
    Not working on chrome as well as of 2020, also throws error unrecognized expression: unsupported pseudo: -webkit-autofill
  • Charles Byrne
    Charles Byrne almost 4 years
    I love dead links.
  • Dabrule
    Dabrule almost 4 years
    Exactly what I needed :)
  • mirek
    mirek almost 4 years
    Not sure when exactly Chrome autofill run, but in $('input, select').on('focusin', function(evt) {...}); I receive autofilled values for all fields already.
  • Antoine O
    Antoine O almost 4 years
    New version maybe?
  • Chanticleer
    Chanticleer over 3 years
    This wont work on Mozilla as the background color is applied via filter, The background color remains the default rgb(255, 255, 255)
  • Mattwmaster58
    Mattwmaster58 over 3 years
    Works in Firefox 86, despite the MDN and caniuse suggesting otherwise.
  • Melebius
    Melebius about 3 years
    The problem for me was using attr('value') instead of val(). Unlike val(), attr('value') does not contain autofilled value (Firefox)!
  • Gawrion
    Gawrion over 2 years
    in new version of FF they changed the styling of the autofill input. Now they use linear-gradient(rgba(255, 249, 145, 0.5), rgba(255, 249, 145, 0.5)) as a property of background-image. I changed the code.
  • Gavin
    Gavin over 2 years
    This answer is old but it still works very well.
  • Jeremy L.
    Jeremy L. over 2 years
    It's possible it's because this answer was so long ago, but this solution and the code at Klarna didn't work for me, as I had to change the hook to "transitionstart" rather than "animationstart". stackoverflow.com/a/41530600
  • etiennejcharles
    etiennejcharles over 2 years
    Needed to add transition timing in css animation-duration: 0.001s - or else the events are not triggered in chrome
  • Zardoz89
    Zardoz89 about 2 years
    On Firefox there isn't a problem for a normal usage, as "change" and "input" events are fired when does a autocomplete. The only real issue if you need to do something ONLY when the autocomplete happens.
  • Zardoz89
    Zardoz89 about 2 years
    Flag as Chrome only solution.