I'm writing a function in C# using Azure Functions and need to get the ip address of the client that called the function, is this possible?
7 Answers
Here is an answer based on the one here.
#r "System.Web"
using System.Net;
using System.Web;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
    string clientIP = ((HttpContextWrapper)req.Properties["MS_HttpContext"]).Request.UserHostAddress;
    return req.CreateResponse(HttpStatusCode.OK, $"The client IP is {clientIP}");
}
- 1
 - 1
 
- 42,443
 - 8
 - 103
 - 117
 
- 
                    So this means one needs to shoehorn a System.Web.dll reference into the function somehow? – Christofer Ohlsson Apr 12 '18 at 11:44
 - 
                    @ChristoferOhlsson unfortunately I thin that's indeed the case. It's not Functions specific, as you'd have the same pattern in Web API (or anything that uses `HttpRequestMessage`). – David Ebbo Apr 12 '18 at 16:44
 - 
                    I dont think this works any more, I get the same collection of IPS for all users, all within the 100* range. I've seen a post on MSDN where someone else confirms that things recently changed and he now gets the same even though MS_HttpContext worked before – Steven Elliott Jun 25 '18 at 11:45
 - 
                    1@StevenElliott look at my updated answer here [link](https://stackoverflow.com/a/46300183/4810304) AzureFunctions now behind a LoadBalancer – Brandy23 Aug 21 '18 at 11:56
 
you should use these function Get the IP address of the remote host
request.Properties["MS_HttpContext"] is not available if you debug precompiled functions local request.Properties[RemoteEndpointMessageProperty.Name] is not available on azure
private string GetClientIp(HttpRequestMessage request)
{
    if (request.Properties.ContainsKey("MS_HttpContext"))
    {
        return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
    }
    if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
    {
        RemoteEndpointMessageProperty prop;
        prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
        return prop.Address;
    }
    return null;
}
Update 21.08.2018: Now Azure Functions are behind a LoadBalancer --> we have to inspect Request-Headers to determine the correct Client IP
private static string GetIpFromRequestHeaders(HttpRequestMessage request)
    {
        IEnumerable<string> values;
        if (request.Headers.TryGetValues("X-Forwarded-For", out values))
        {
            return values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
        }
        return "";
    }
- 269
 - 2
 - 8
 
- 
                    Nice, thanks! Was having a hard time with everyone saying "MS_HttpContext", yet it not being present in my function. – user3734274 Mar 24 '18 at 06:58
 - 
                    
 
Here is an extension method based on what I am seeing in
.Net Core 3.1
public static IPAddress GetClientIpn(this HttpRequest request)
{
    IPAddress result = null;
    if (request.Headers.TryGetValue("X-Forwarded-For", out StringValues values))
    {
        var ipn = values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
        IPAddress.TryParse(ipn, out result);
    }
    if (result == null)
    {
        result = request.HttpContext.Connection.RemoteIpAddress;
    }
    return result;
}
.NET 6.+
        public static IPAddress GetClientIpn(this HttpRequestMessage request)
        {
            IPAddress result = null;
            if (request.Headers.TryGetValues("X-Forwarded-For", out IEnumerable<string> values))
            {
                var ipn = values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
                IPAddress.TryParse(ipn, out result);
            }
            return result;
        }
- 6,051
 - 2
 - 40
 - 48
 
- 
                    1
 - 
                    While you're there, you can search the headers to determine if any comparable header is available. – N-ate Jan 31 '23 at 20:10
 
Now that Azure functions get an HttpRequest parameter, and they're behind a load balancer, this function to get the IP address works for me:
private static string GetIpFromRequestHeaders(HttpRequest request)
{
      return (request.Headers["X-Forwarded-For"].FirstOrDefault() ?? "").Split(new char[] { ':' }).FirstOrDefault();
}
- 21,581
 - 10
 - 69
 - 79
 
- 81
 - 1
 - 4
 
- 
                    Unfortunately, this does work, but it returns the IP address of an internal box a 10.x.x.x address as of Decmeber 2021. Even using Azure Insights - their logs do not even provide the IP address of the clients. – Redgum Dec 04 '21 at 07:58
 
Update 18-Oct-2019:
The solution I tried is much easier and quicker and is mentioned below stepwise. But some more lengthy/tricky alternates are available @ https://learn.microsoft.com/en-us/azure/azure-monitor/app/ip-collection:
- Login into Azure portal.
 - Open a new tab in same browser while you are logged in and dial “http://Resources.Azure.Com”
 - This is Azure back end services portal so being slightly careful in making changes would be great.
 - Expand SUBSCRIPTIONS section from the left panel and expand your Azure Subscription where app insight resource is located.
 - Expand Resource Groups section and expand the Resource Group where app insights resource is.
 - Expand the Providers section and find the Microsoft.Insights provider and expand it.
 - Expand the Components section and find and select your App Insight Instance by name.
 - On the right top change your mode to Read Write from Read Only.
 - Click EDIT button on the Rest API call.
 - ADD NEW “"DisableIpMasking": true property to properties section.
 - Press PUT button to apply changes.
 - Now your App Insight is enabled to start collecting Client IP addresses.
 - Do some queries on the Function.
 - Refresh and Test the App Insights data after about 5 to 10 minutes.
 
- 41
 - 1
 
- 
                    This combined with: ```csharp IPAddress result = null; if (req.Headers.TryGetValue("X-Forwarded-For", out StringValues values)) { var ipn = values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault(); IPAddress.TryParse(ipn, out result); } if (result == null) { result = req.HttpContext.Connection.RemoteIpAddress; } string IP = result?.ToString(); ``` Worked – Trevor F Apr 07 '21 at 13:24
 
As mentioned already by others, the old method of looking at MS_HttpContext no longer works.  Further, while the method of looking at the headers for X-Forwarded-For does work, it only works after being published in Azure - it doesn't return a value when you're running locally.  That may matter if you prefer testing locally to minimize any potential cost-impact, but still want to be able to see that everything works correctly.
To see the IP address even when running locally, try this instead:
using Microsoft.AspNetCore.Http;
And then:
String RemoteIP = ((DefaultHttpContext)req.Properties["HttpContext"])?.Connection?.RemoteIpAddress?.ToString();
This is working for me currently in Azure Functions V3.0.
- 484
 - 3
 - 12
 
- 
                    'HttpRequestMessage.Properties' is obsolete: 'Use Options instead.' – user160357 Aug 17 '22 at 00:06
 
In a .NET 6.0 function, within the Run() function of the operation, this can be accessed of the HttpRequest req object:
    public static class PingOperation
    {
        [FunctionName("ping")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            log.LogInformation($"PingOperation requested from: {req.HttpContext.Connection.RemoteIpAddress}:{req.HttpContext.Connection.RemotePort}");
            string responseMessage = "This HTTP triggered function executed successfully.";
            return new OkObjectResult(responseMessage);
        }
    }
- 2,707
 - 5
 - 31
 - 36
 
- 79
 - 1
 - 3