diff --git a/lib/mobilizon/config.ex b/lib/mobilizon/config.ex
index 553f6e3d3..7b2ebbe48 100644
--- a/lib/mobilizon/config.ex
+++ b/lib/mobilizon/config.ex
@@ -30,6 +30,10 @@ defmodule Mobilizon.Config do
   @spec instance_email_reply_to :: String.t()
   def instance_email_reply_to, do: instance_config()[:email_reply_to]
 
+  @spec instance_user_agent :: String.t()
+  def instance_user_agent,
+    do: "#{instance_name()} #{instance_hostname()} - Mobilizon #{Mix.Project.config()[:version]}"
+
   @spec get(module | atom) :: any
   def get(key), do: get(key, nil)
 
diff --git a/lib/service/geospatial/addok.ex b/lib/service/geospatial/addok.ex
index b209ec0d9..8dd88d52b 100644
--- a/lib/service/geospatial/addok.ex
+++ b/lib/service/geospatial/addok.ex
@@ -5,6 +5,7 @@ defmodule Mobilizon.Service.Geospatial.Addok do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Provider
+  alias Mobilizon.Config
 
   require Logger
 
@@ -18,12 +19,14 @@ defmodule Mobilizon.Service.Geospatial.Addok do
   """
   @spec geocode(String.t(), keyword()) :: list(Address.t())
   def geocode(lon, lat, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:geocode, %{lon: lon, lat: lat}, options)
 
     Logger.debug("Asking addok for addresses with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, %{"features" => features}} <- Poison.decode(body) do
       process_data(features)
     end
@@ -35,11 +38,13 @@ defmodule Mobilizon.Service.Geospatial.Addok do
   """
   @spec search(String.t(), keyword()) :: list(Address.t())
   def search(q, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:search, %{q: q}, options)
     Logger.debug("Asking addok for addresses with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, %{"features" => features}} <- Poison.decode(body) do
       process_data(features)
     end
diff --git a/lib/service/geospatial/map_quest.ex b/lib/service/geospatial/map_quest.ex
index 1c45a38b6..084836a03 100644
--- a/lib/service/geospatial/map_quest.ex
+++ b/lib/service/geospatial/map_quest.ex
@@ -11,6 +11,7 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Provider
+  alias Mobilizon.Config
 
   require Logger
 
@@ -29,6 +30,8 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
     api_key = Keyword.get(options, :api_key, @api_key)
     limit = Keyword.get(options, :limit, 10)
     open_data = Keyword.get(options, :open_data, true)
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
 
     prefix = if open_data, do: "open", else: "www"
 
@@ -38,7 +41,8 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
            HTTPoison.get(
              "https://#{prefix}.mapquestapi.com/geocoding/v1/reverse?key=#{api_key}&location=#{
                lat
-             },#{lon}&maxResults=#{limit}"
+             },#{lon}&maxResults=#{limit}",
+             headers
            ),
          {:ok, %{"results" => results, "info" => %{"statuscode" => 0}}} <- Poison.decode(body) do
       results |> Enum.map(&process_data/1)
@@ -54,6 +58,8 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
   """
   @spec search(String.t(), keyword()) :: list(Address.t())
   def search(q, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     limit = Keyword.get(options, :limit, 10)
     api_key = Keyword.get(options, :api_key, @api_key)
 
@@ -71,7 +77,7 @@ defmodule Mobilizon.Service.Geospatial.MapQuest do
     Logger.debug("Asking MapQuest for addresses with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, %{"results" => results, "info" => %{"statuscode" => 0}}} <- Poison.decode(body) do
       results |> Enum.map(&process_data/1)
     else
diff --git a/lib/service/geospatial/nominatim.ex b/lib/service/geospatial/nominatim.ex
index 47dda84f7..c00e0e936 100644
--- a/lib/service/geospatial/nominatim.ex
+++ b/lib/service/geospatial/nominatim.ex
@@ -5,6 +5,7 @@ defmodule Mobilizon.Service.Geospatial.Nominatim do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Provider
+  alias Mobilizon.Config
 
   require Logger
 
@@ -19,11 +20,13 @@ defmodule Mobilizon.Service.Geospatial.Nominatim do
   """
   @spec geocode(String.t(), keyword()) :: list(Address.t())
   def geocode(lon, lat, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:geocode, %{lon: lon, lat: lat}, options)
     Logger.debug("Asking Nominatim for geocode with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, body} <- Poison.decode(body) do
       [process_data(body)]
     end
@@ -35,11 +38,13 @@ defmodule Mobilizon.Service.Geospatial.Nominatim do
   """
   @spec search(String.t(), keyword()) :: list(Address.t())
   def search(q, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:search, %{q: q}, options)
     Logger.debug("Asking Nominatim for addresses with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, body} <- Poison.decode(body) do
       body |> Enum.map(fn entry -> process_data(entry) end) |> Enum.filter(& &1)
     end
diff --git a/lib/service/geospatial/photon.ex b/lib/service/geospatial/photon.ex
index 7bf11131d..df954305c 100644
--- a/lib/service/geospatial/photon.ex
+++ b/lib/service/geospatial/photon.ex
@@ -5,6 +5,7 @@ defmodule Mobilizon.Service.Geospatial.Photon do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Provider
+  alias Mobilizon.Config
 
   require Logger
 
@@ -20,11 +21,13 @@ defmodule Mobilizon.Service.Geospatial.Photon do
   """
   @spec geocode(number(), number(), keyword()) :: list(Address.t())
   def geocode(lon, lat, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:geocode, %{lon: lon, lat: lat}, options)
     Logger.debug("Asking photon for reverse geocoding with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, %{"features" => features}} <- Poison.decode(body) do
       process_data(features)
     end
@@ -36,11 +39,13 @@ defmodule Mobilizon.Service.Geospatial.Photon do
   """
   @spec search(String.t(), keyword()) :: list(Address.t())
   def search(q, options \\ []) do
+    user_agent = Keyword.get(options, :user_agent, Config.instance_user_agent())
+    headers = [{"User-Agent", user_agent}]
     url = build_url(:search, %{q: q}, options)
     Logger.debug("Asking photon for addresses with #{url}")
 
     with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
-           HTTPoison.get(url),
+           HTTPoison.get(url, headers),
          {:ok, %{"features" => features}} <- Poison.decode(body) do
       process_data(features)
     end
diff --git a/test/mobilizon/service/geospatial/addok_test.exs b/test/mobilizon/service/geospatial/addok_test.exs
index d81cfaab4..7dbf948dc 100644
--- a/test/mobilizon/service/geospatial/addok_test.exs
+++ b/test/mobilizon/service/geospatial/addok_test.exs
@@ -7,20 +7,31 @@ defmodule Mobilizon.Service.Geospatial.AddokTest do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Addok
+  alias Mobilizon.Config
+
+  @httpoison_headers [
+    {"User-Agent",
+     "#{Config.instance_name()} #{Config.instance_hostname()} - Mobilizon #{
+       Mix.Project.config()[:version]
+     }"}
+  ]
 
   @endpoint get_in(Application.get_env(:mobilizon, Addok), [:endpoint])
   @fake_endpoint "https://domain.tld"
 
   describe "search address" do
     test "produces a valid search address" do
-      with_mock HTTPoison, get: fn _url -> "{}" end do
+      with_mock HTTPoison, get: fn _url, _headers -> "{}" end do
         Addok.search("10 Rue Jangot")
-        assert_called(HTTPoison.get("#{@endpoint}/search/?q=10%20Rue%20Jangot&limit=10"))
+
+        assert_called(
+          HTTPoison.get("#{@endpoint}/search/?q=10%20Rue%20Jangot&limit=10", @httpoison_headers)
+        )
       end
     end
 
     test "produces a valid search address with options" do
-      with_mock HTTPoison, get: fn _url -> "{}" end do
+      with_mock HTTPoison, get: fn _url, _headers -> "{}" end do
         Addok.search("10 Rue Jangot",
           endpoint: @fake_endpoint,
           limit: 5,
@@ -28,7 +39,10 @@ defmodule Mobilizon.Service.Geospatial.AddokTest do
         )
 
         assert_called(
-          HTTPoison.get("#{@fake_endpoint}/search/?q=10%20Rue%20Jangot&limit=5&lat=49&lon=12")
+          HTTPoison.get(
+            "#{@fake_endpoint}/search/?q=10%20Rue%20Jangot&limit=5&lat=49&lon=12",
+            @httpoison_headers
+          )
         )
       end
     end
diff --git a/test/mobilizon/service/geospatial/map_quest_test.exs b/test/mobilizon/service/geospatial/map_quest_test.exs
index 1176ef316..00d535cae 100644
--- a/test/mobilizon/service/geospatial/map_quest_test.exs
+++ b/test/mobilizon/service/geospatial/map_quest_test.exs
@@ -7,6 +7,14 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.MapQuest
+  alias Mobilizon.Config
+
+  @httpoison_headers [
+    {"User-Agent",
+     "#{Config.instance_name()} #{Config.instance_hostname()} - Mobilizon #{
+       Mix.Project.config()[:version]
+     }"}
+  ]
 
   describe "search address" do
     test "without API Key triggers an error" do
@@ -17,7 +25,7 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
 
     test "produces a valid search address with options" do
       with_mock HTTPoison,
-        get: fn _url ->
+        get: fn _url, _headers ->
           {:ok,
            %HTTPoison.Response{
              status_code: 200,
@@ -32,7 +40,8 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
 
         assert_called(
           HTTPoison.get(
-            "https://open.mapquestapi.com/geocoding/v1/address?key=toto&location=10%20Rue%20Jangot&maxResults=5"
+            "https://open.mapquestapi.com/geocoding/v1/address?key=toto&location=10%20Rue%20Jangot&maxResults=5",
+            @httpoison_headers
           )
         )
       end
diff --git a/test/mobilizon/service/geospatial/nominatim_test.exs b/test/mobilizon/service/geospatial/nominatim_test.exs
index e436afbe3..04bec7da4 100644
--- a/test/mobilizon/service/geospatial/nominatim_test.exs
+++ b/test/mobilizon/service/geospatial/nominatim_test.exs
@@ -7,11 +7,19 @@ defmodule Mobilizon.Service.Geospatial.NominatimTest do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Nominatim
+  alias Mobilizon.Config
+
+  @httpoison_headers [
+    {"User-Agent",
+     "#{Config.instance_name()} #{Config.instance_hostname()} - Mobilizon #{
+       Mix.Project.config()[:version]
+     }"}
+  ]
 
   describe "search address" do
     test "produces a valid search address with options" do
       with_mock HTTPoison,
-        get: fn _url ->
+        get: fn _url, _headers ->
           {:ok, %HTTPoison.Response{status_code: 200, body: "[]"}}
         end do
         Nominatim.search("10 Rue Jangot",
@@ -21,7 +29,8 @@ defmodule Mobilizon.Service.Geospatial.NominatimTest do
 
         assert_called(
           HTTPoison.get(
-            "https://nominatim.openstreetmap.org/search?format=jsonv2&q=10%20Rue%20Jangot&limit=5&accept-language=fr&addressdetails=1"
+            "https://nominatim.openstreetmap.org/search?format=jsonv2&q=10%20Rue%20Jangot&limit=5&accept-language=fr&addressdetails=1",
+            @httpoison_headers
           )
         )
       end
diff --git a/test/mobilizon/service/geospatial/photon_test.exs b/test/mobilizon/service/geospatial/photon_test.exs
index 630035c60..009bccdb4 100644
--- a/test/mobilizon/service/geospatial/photon_test.exs
+++ b/test/mobilizon/service/geospatial/photon_test.exs
@@ -7,11 +7,19 @@ defmodule Mobilizon.Service.Geospatial.PhotonTest do
 
   alias Mobilizon.Addresses.Address
   alias Mobilizon.Service.Geospatial.Photon
+  alias Mobilizon.Config
+
+  @httpoison_headers [
+    {"User-Agent",
+     "#{Config.instance_name()} #{Config.instance_hostname()} - Mobilizon #{
+       Mix.Project.config()[:version]
+     }"}
+  ]
 
   describe "search address" do
     test "produces a valid search address with options" do
       with_mock HTTPoison,
-        get: fn _url ->
+        get: fn _url, _headers ->
           {:ok, %HTTPoison.Response{status_code: 200, body: "{\"features\": []"}}
         end do
         Photon.search("10 Rue Jangot",
@@ -20,7 +28,10 @@ defmodule Mobilizon.Service.Geospatial.PhotonTest do
         )
 
         assert_called(
-          HTTPoison.get("https://photon.komoot.de/api/?q=10%20Rue%20Jangot&lang=fr&limit=5")
+          HTTPoison.get(
+            "https://photon.komoot.de/api/?q=10%20Rue%20Jangot&lang=fr&limit=5",
+            @httpoison_headers
+          )
         )
       end
     end