I'm manually implementing a WiFi captive portal. I've got everything pretty much working BUT a single hitch: i want everyone to see their mobile OSs' (or computer OSs') captive portal popup for a flawless experience.

Since each one of them has its own twisted way of doing it i'm seemingly unable to get a consistent cross-platform experience.

To make this happen, can I have some help to describe either (1) what URL requests from WiFi clients need to be redirected to a login page, and/or (2) what nginx or apache web server configuration can be used to redirect WiFi clients to a login page?

My captive portal login page in this example is http://captiveportal.lan . Here are some of the Operating Systems I am trying to resolve this for.

Android 4/5/6

  • Apache:
    RedirectMatch 302 /generate_204 http://captiveportal.lan
  • nginx: ?

Previous Android versions

  • Apache: ?
  • nginx: ?

iOS 8

  • Apache .htaccess:
    RewriteEngine on
    RewriteCond %{HTTP_USER_AGENT} ^CaptiveNetworkSupport(.*)$ [NC]
    RewriteRule ^(.*)$ http://captiveportal.lan [L,R=302]

  • nginx: ?

Previous iOS versions

  • Apache: ?
  • nginx: ?

Windows phone

  • Apache:
    RedirectMatch 302 /ncsi.txt http://captiveportal.lan
  • nginx: ?

Windows 7\8\10

  • Apache: see windows phone (works on win7).
  • nginx: ?

Mac OS

  • Apache: ?
  • nginx: ?

Amazon Kindle - does it have a popup?

  • Apache: ?
  • nginx: ?
  • 5
    No it is not too broad, it is simply a multi-platform issue. THE MOST multi-platform issue there can be, perhaps. It has also reached the "notable question" status (more than 2500 views) so people are really interested in it and you're rendering a HUGE disservice to all by preventing contributions from pouring in. For shame! – ppparadox May 1 '16 at 15:56
  • Thanks so much for the post; it allowed me to do this unix.stackexchange.com/questions/386242/… – Rui F Ribeiro Aug 15 '17 at 17:39

All mobile OS just check a web page to decide whether they're behind a captive portal or not.

The mechanism is this:

  1. GET/POST http://foo.com/bar.html
  2. If bar.html == [expected content] > Open Internet
  3. If bar.html != [expected content] > Captive Portal
  4. If bar.html[status] != SUCCESS > No Network

Also, for iOS, you need to have a domain for your WiFi network as it assumes a domainless network without access is a home network and just marks it as No Network instead of Captive Portal.

Just make sure to explicitly redirect the following urls to your captive portal with HTTP Success:

Android / Chromebook:

  • clients3.google.com

iOS 6:

  • gsp1.apple.com
  • *.akamaitechnologies.com

iOS 7:

  • www.appleiphonecell.com
  • www.airport.us
  • *.apple.com.edgekey.net
  • *.akamaiedge.net
  • *.akamaitechnologies.com

iOS 8/9:


  • ipv6.msftncsi.com
  • www.msftncsi.com

Many vendors have also began to use the User Agent "CaptiveNetworkSupport", though it's not as common as the URL method above. Just check for that UA and always give it your portal page...doesn't work 100% though.

I use the URL method and it's been working fine.

  • Care to share some working webserver conf\firewall rules\php snippets you use to obtain the popup? – ppparadox Sep 23 '15 at 14:26
  • Looks like Android v6 is using a different url. connectivitycheck.gstatic.com which is mentioned here – DavidT Jan 28 '16 at 13:41
  • Why would you have to explicitly redirect the test URLs? Wouldn't you just serve the login page for every URL until the user logged in? – AShelly Dec 2 '16 at 22:16

Amazon Kindle (Fire)

The Amazon Kindle (Fire) makes the following request, and if it cannot be retrieved "... it assumes that the user has to login and throws up a Log In screen.":

iOS 8.4

For the latest iOS I had to match all URIs for requests to http://captive.apple.com - not just "/hotspot-detect.html".

iOS 8.4 clients are making requests with randomly generated URIs (e.g. "/xmqPyZUv/3r8jTjv8.html" and "/7exN0TV7q0COX0/eKlBU8baU2tape/fjXUzDHBdE6W0O/BGbw7iYU2DVBh1/sVBlx8icYzTTtE.html") in URL requests to the following domains to detect a captive portal:

  • 1
    Does iOS 8.4 set the UserAgent to "CaptiveNetworkSupport"? Care to share some working webserver conf\firewall rules\php snippets you use to obtain the popup? Also, why has someone downvoted you without bothering to explain why? Stupid people... – ppparadox Sep 23 '15 at 14:24
  • The exact agent string is "CaptiveNetworkSupport-277.10.5 wispr". When I redirect these requests (listed in this question) to a login page, Apple iOS will pop up a login page, and Android will show a login header bar. After successfully logging in on the Login page, the captive portal system must allow these HTTP requests to be successful in order for the popup window and login bar to disappear. I have successfully tested this in a custom captive portal I created using only Linux, dnsmasq, and Apache httpd server. – Russell E Glaue Sep 23 '15 at 14:50
  • Forgot to ask if the Kindle sets that user agent too. – ppparadox Sep 23 '15 at 14:55
  • 1
    For kindle I am seeing "Dalvik/2.1.0 (Linux; U; Android 5.0.1; VS985 4G Build/LRX21Y)" (maybe it is a kindle app?). This thread mobileread.com/forums/showthread.php?t=188439 says "Mozilla /5.0 (Linux; like iPhone; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0" – Russell E Glaue Sep 23 '15 at 15:00
  • 1
    @ppparadox I don't know why I got the down vote seconds after I posted. If you like my contribution, please give me an upvote. Thanks. – Russell E Glaue Sep 23 '15 at 15:04

Not the answer you're looking for?Browse other questions tagged or ask your own question.