Prerequisites
- A .NET 6+ project with
IpApiIoadded - A free ip-api.io API key
Catch the typed exceptions
Each exception derives from IpApiException and carries a StatusCode and Message. Catch the specific type you care about first.
using IpApiIo;
using IpApiIo.Exceptions;
try
{
var info = await client.LookupAsync("8.8.8.8");
Console.WriteLine(info.Ip);
}
catch (RateLimitException ex)
{
Console.WriteLine($"quota hit — resets at {ex.Reset}");
}
catch (AuthenticationException)
{
Console.WriteLine("check your API key");
}
catch (InvalidRequestException ex)
{
Console.WriteLine($"bad request: {ex.Message}");
}
catch (ServerException)
{
Console.WriteLine("ip-api.io is having trouble, try later");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"transport error: {ex.Message}");
} HttpRequestException (or TaskCanceledException on timeout) —
they are not an IpApiException.
Handle rate limits with RateLimitException
On HTTP 429 you get RateLimitException, carrying the x-ratelimit-* header values (-1 when a header is absent). Because the client never retries, Reset tells you when to.
catch (RateLimitException ex)
{
Console.WriteLine(ex.Limit); // your quota for the window
Console.WriteLine(ex.Remaining); // requests left (0 here)
Console.WriteLine(ex.Reset); // Unix timestamp when quota renews
// schedule a retry at ex.Reset instead of hammering the API
} Check quota proactively with RateLimitAsync
Read your current limits without triggering a 429, so you can throttle in advance.
var rl = await client.RateLimitAsync();
Console.WriteLine(rl.PlanName);
Console.WriteLine($"{rl.IpApi.Remaining} / {rl.IpApi.Limit}");
Console.WriteLine($"{rl.EmailApi.UsagePercent:F1}% used"); Account usage with UsageSummaryAsync
Aggregate usage for the current period — handy for dashboards and internal alerts.
var usage = await client.UsageSummaryAsync();
Console.WriteLine($"{usage.TotalRequests} {usage.SuccessfulRequests}");
Console.WriteLine($"{usage.RateLimitedRequests} {usage.QuotaConsumed}");
Console.WriteLine($"{usage.PeriodStart} {usage.PeriodEnd}");