25
votes

The user agent of Safari on iPadOS beta is at this point exactly the same as Safari on macOS. Is there any other way to tell an iPad from a Mac?

iPad running iOS
Mozilla/5.0 (iPad; CPU OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1

iPadOS, developer beta 1
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS, beta 2, simulator
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS, beta 3, (simulator)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS, developer beta 3
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS, developer beta 4
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS 13.1, developer beta 1
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS 13.1, developer beta 2
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

iPadOS 13.1, developer beta 3
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Safari/605.1.15

iPadOS 13.1, developer beta 4
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Safari/605.1.15

macOS Catalina 
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

macOS (older version)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Safari/605.1.15

macOS Catalina developer beta 7
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

macOS Catalina developer beta 8
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Safari/605.1.15

When playing HLS video, the iPadOS agent seems to be:

AppleCoreMedia/1.0.0.17A5821e (iPad; U; CPU OS 13_1 like Mac OS X; en_us)
4
I'm wondering if this is actually another case of "spoofing" mentioned here. stackoverflow.com/a/7976057/129202Jonny
I added the user agent of next macOS Catalina. Note that it is EXACTLY the same as iPadOS.Jonny
I think you just can't ??? Currently my solution is, if user-agent shows 10.15, show a pop-up ask if is iPadOS or macOS.Alen Liang
Looking for a solution to this issue as well, and the only thing I can see that may be of use is this: Navigator.standalone From developer.mozilla.org/en-US/docs/Web/API/Navigator: "Returns a boolean indicating whether the browser is running in standalone mode. Available on Apple's iOS Safari only." Trying to get a machine with macOS 10.15 to see if it returns a value on desktop safari, but on my 10.14 macOS safari it was undefined. Returned a value in 10.15 iOS/ipadOS in my simulatoruser2879041

4 Answers

24
votes

I'm using this test client side:

   if (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2) {
     ...must be iPad OS...

Since there's no official touch screen for Mac, it seems pretty safe. The actual value of maxTouchPoints on the iPad is 5, BTW.

12
votes

I would not generally recommend this, and I haven't tested it much (using something similar in production since September 2019), but one way could be to detect the existence of TouchEvent on the client side, and match it with the state of the user agent to account for older iOS versions of iPad:s. YMMV. Likely not very future safe.

function isIpad() {
    const ua = window.navigator.userAgent;
    if (ua.indexOf('iPad') > -1) {
        return true;
    }

    if (ua.indexOf('Macintosh') > -1) {
        try {
            document.createEvent("TouchEvent");
            return true;
        } catch (e) {}
    }

    return false;
}
2
votes

I'm using this works fine:

const ua = window.navigator.userAgent.toLowerCase();
const isiPad = ua.indexOf('ipad') > -1 || ua.indexOf('macintosh') > -1 && 'ontouchend' in document;
1
votes

as @Jonny mentioned you can try and detect touch events, this is the solution i currently use

function isTouchDevice() {
  if (typeof window === 'undefined') return false
  const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ')
  function mq(query) {
    return typeof window !== 'undefined' && window.matchMedia(query).matches
  }
  if ('ontouchstart' in window || (window?.DocumentTouch && document instanceof DocumentTouch)) return true
  const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('') // include the 'heartz' - https://git.io/vznFH
  return mq(query)
}

interesting post on detecting touch events

and another note, Firefox on Ipad uses the same safari user-agent :/