How to get an IP address using Ruby on Rails

Last Updated Nov 21, 2021
Emma Jagger

Engineer, maker, Google alumna, CMU grad

For mail to arrive in the right recipient's mailbox, the exact address, including country, city, zip code, and street must be specified. This way, the post office and its employees know where the mail should be sent and how to route it. The same is true on the Internet: any device connected requires an address to communicate with other devices. This address is known as the IP address.

Thus all visitors who visit your website are identified by their IP address, which is mandatory for the exchange of data, but can also serve several other purposes.

As a general rule, a website does not have to worry about its hosting infrastructure. And yet, there is a special case for which a web developer must understand the network environment around the server machine: when it is necessary to retrieve its visitors' IP address.

The task seems simple since the webserver knows its visitors' IP addresses, which can be retrieved from one of its variables. And yet, there are complications. If you're not developer or just want to get personal information, you can use our tool to find out what is your IP address and location.

What can I do with a visitor's IP address?

Web servers automatically record the activity of your visitors by identifying them by their IP address. These activities can be found in the server's log files, which are extremely useful to understand their behavior on your site and to optimize its structure and the content of your pages.

But IP addresses also make it possible to identify with some precision the geographical position of your visitors. This is called geolocation.

What if most of your visitors are coming from a non-English speaking country while your site is entirely in English? Geolocation allows you to detect such a situation and know which country your visitors are coming from. With such information, you can decide to translate your site, offer these visitors content in their language, or review your linking profile and improve your SEO to get better natural traffic.

A simple method to retrieve the IP address using Ruby on Rails

The request object available in Rails controllers exposes many helpful methods to get information about the client's request (the visitor of your site). You can use the request.ip method to get the IP address of the visitor (which returns the client's IP address) and we will observe some peculiarities:


class HomeController < ApplicationController
  def index
    render plain: "You IP address is #{client_ip}"
  end

  private def client_ip
    request.ip
  end
end

For example, if your website is behind a reverse proxy, every call to request.ip will return the proxy's IP address, not the visitor's.

Obviously, if you run this code on your local machine, and depending on its configuration, the page will display "Your IP address is 127.0.0.1" or "Your IP address is ::1". The first case corresponds to a IPv4 address, and the second to a IPv6 address. The two addresses have in common that they are both a loopback addresses, which are used by any computer to connect to itself.

To get a more interesting result, you have to deploy your code on a public server at a hosting company. Once this is done, get your real public IP address using a third party service as a reference. You can find such a service on Google. Then access your site to compare the results. If everything went well, your script would show you the same IP address as the one given by the third party service.

Don't reinvent the wheel.
Abstract's APIs are production-ready now.

Abstract's suite of API's are built to save you time. You don't need to be an expert in email validation, IP geolocation, etc. Just focus on writing code that's actually valuable for your app or business, and we'll handle the rest.

Get started for free

Why is it necessary to know the infrastructure of your hosting provider?

As a web developer, you may have already heard of load-balancer, DDoS mitigator, or more simply proxy or firewall. You may not have bothered until now to understand how they work. But to get the IP address of your visitors, you will need to understand some of the basic mechanisms.

A proxy or firewall is positioned between your web server and your visitor. Its role is to protect your web server, which is certainly configured only to accept connections that have been filtered by the proxy.

In such a configuration, if you run the script we wrote above, you will get an address that doesn't match your IP address, and if you search a little deeper, you will quickly understand that it corresponds to the IP address of the proxy. Indeed, the proxy modifies the client request to make your server believe that it is the request's origin. The proxy thus ensures that all communications pass through it.

In this case, you will have to use the remote_ip method, which is also available in the controllers, verifying that the IP address has been changed by a proxy and returning the client's real address.

It has to be understood that, even if request is an ActionDispatch::Request object, its method remote_ip is actually a proxy for the ActionDispatch::RemoteIp middleware.

request.remote_ip checks all IPs present in the HTTP header, looking for fields generally used by firewalls, load balancers, or proxies, such as HTTP_X_FORWARDED_FOR, and make a guess to return what seems to be the correct visitor's IP address.

Here is how to modify your script:


class HomeController < ApplicationController
  def index
    render plain: "You IP address is #{client_ip}"
  end

  private def client_ip
    request.remote_ip
  end
end

From now, if you connect to your server, you will see your real IP address.

You should use request.remote_ip only if you are behind a proxy or a firewall, or you would be vulnerable to IP spoofing attacks: as request.remote_ip checks for fields in the HTTP header that proxies usually set, and if you are not behind a proxy, then anyone could manually set a false IP address in the headers. Doing so is as simple as this:


curl -H "X-Forwarded-For: 5.5.5.5" http://your.website.com

So before choosing between request.ip and request.remote_ip to get your visitors' IP addresses, you need to know a little about your host infrastructure. You could eventually analyze the HTTP headers when a request reaches your application to understand from which header you can get the real IP address.

How to know if the visitor connects through a VPN using Ruby on Rails

If you connect to the Internet through a VPN service and access your IP address detection script, you will find that the address displayed is not your real address but the VPN's exit address.

Since VPN is a service to protect Internet users, they make sure to prevent websites from discovering their users' real IP address. As a result, your script won't determine if the user is behind a VPN server or not, and therefore it will be impossible for you to know if the IP address thus obtained is real.

Detect if a user is using a VPN service

To do this, it is necessary to use a service that analyzes the IP addresses of your visitors and determines, among other things, whether this address corresponds to an exit address of a VPN service. You may be able to develop such a service by yourself, but you would have to update the list of VPNs' list of known IPs constantly, which is extremely time-consuming.

Abstract provides such a service for free, responding very fast and always up to date, through the geolocation API. Just create an account in a few seconds, which gets you your private API key. Then a simple HTTP call allows you to determine if the visitor is behind a VPN.


class HomeController < ApplicationController
  def index
    string = "You IP address is #{client_ip}"
    if behind_vpn?
      string << " and you are using a VPN"
    end

    render plain: string
  end

  private
  def client_ip
    request.remote_ip
  end

  def behind_vpn?
    uri = URI('https://ipgeolocation.abstractapi.com/v1/?api_key=#{api_key}&ip_address=#{client_ip}')

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER

    request =  Net::HTTP::Get.new(uri)
    response = JSON.parse(http.request(request))

    ! response['security']['is_vpn']
  end
end

Doing geolocation in Ruby on Rails

As mentioned above, your visitors' IP address can be used to understand better your audience's demographics, which you can analyze to gain huge advantages in marketing and content targeting.

The less costly approach is to call an external API to translate your visitor's IP addresses to their physical location. Abstract IP Geolocation API provide GPS coordinates, country, city, timezone, and a visitor's currency from its IP address with a simple GET request.

After creating a free account, you obtain your personal API key and can start fetching information. Here is an example of implementation:


require 'net/http'
require 'net/https'

def make_abstract_request(api_key, ip_address)
  uri = URI('https://ipgeolocation.abstractapi.com/v1/?api_key=#{api_key}&ip_address=#{ip_address}')

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  request =  Net::HTTP::Get.new(uri)

  response = http.request(request)
  puts "Status code: #{ response.code }"
  puts "Response body: #{ response.body }"
rescue StandardError => error
  puts "Error (#{ error.message })"
end

api_key = "THE_API_KEY_IN_YOUR_DASHBOARD"
ip_address = "IP_ADDRESS"

make_abstract_request(api_key, ip_address)

Here is an example of a response:


{
  "ip_address": "17.52.21.100",
  "city": "Cupertino",
  "city_geoname_id": 5341145,
  "region": "California",
  "region_iso_code": "CA",
  "region_geoname_id": 5332921,
  "postal_code": "95014",
  "country": "United States",
  "country_code": "US",
  "country_geoname_id": 6252001,
  "country_is_eu": false,
  "continent": "North America",
  "continent_code": "NA",
  "continent_geoname_id": 6255149,
  "longitude": -122.03,
  "latitude": 37.3219,
  "security": {
    "is_vpn": false
  },
  "timezone": {
    "name": "America/Los_Angeles",
    "abbreviation": "PST",
    "gmt_offset": -8,
    "current_time": "01:43:33",
    "is_dst": false
  },
  "flag": {
    "emoji": "🇺🇸",
    "unicode": "U+1F1FA U+1F1F8",
    "png": "https://static.abstractapi.com/country-flags/US_flag.png",
    "svg": "https://static.abstractapi.com/country-flags/US_flag.svg"
  },
  "currency": {
    "currency_name": "USD",
    "currency_code": "USD"
  },
  "connection": {
    "autonomous_system_number": 714,
    "autonomous_system_organization": "Apple Inc.",
    "connection_type": "Corporate",
    "isp_name": "Apple Inc.",
    "organizaton_name": "Apple Inc"
  }
}

Abstract's IP Geolocation API makes it easy to geolocate IP addresses in Ruby on Rails. Try it for free today.

Get started for free
Abstract's IP Geolocation API makes it easy to geolocate IP addresses in Ruby on Rails. Try it for free today.
Get started