Retrofit 2 — Dynamic Request Headers with @HeaderMap

In the past, we've explored how to add request headers with Retrofit and how to statically change request headers with OkHttp. In this blog post, we'll dig into how you can add a dynamic amount of request headers to your Retrofit requests.

This is a new feature of Retrofit 2.1, so make sure you've updated your app before you try it out.

Of course, this is not the only post in our Retrofit series. If you're interested in the other topics, check the following series outline:

Retrofit Series Overview

  1. Introduction to Call Adapters (Coming soon)
  2. Custom Call Adapter to Separate OnResponse Callback (Coming soon)
  3. How to Integrate RxJava 1.x Call Adapter (Coming soon)
  4. How to Integrate RxJava 2.x Call Adapter (Coming soon)
  5. How to Integrate Guava Call Adapter (Coming soon)
  6. Custom Call Adapter to Separate Network and Gson Errors (Coming soon)
  1. Callbacks (Coming soon)
  2. Annotations (Coming soon)
  3. Fluent Interface with Builders (Coming soon)

Dynamic Request Headers

Unfortunately, the approaches we've shown you in the previous blog posts are all static. While you can change the value of the headers, you cannot dynamically select which headers you actually send. If you need to decide at runtime which headers are added to your request, @HeaderMap is a possible solution.

Similar to the @Header annotation, you need to declare the @HeaderMap as one of the interface parameters. The type of the parameter needs to an implementation of the Java Map interface:

public interface TaskService {  
    Call<List<Task>> getTasks(
        @HeaderMap Map<String, String> headers

Using the interface we've declared above is quite simple. You can just create a Map instance and fill it with values depending on your needs. Retrofit will add every non-null element of the @HeaderMap as a request header.

TaskService taskService = ServiceGenerator.createService(TaskService.class);

Map<String, String> map = new HashMap<>();  
map.put("Page", String.valueOf(page));

if (BuildConfig.DEBUG) {  
    map.put("Accept", "application/vnd.yourapi.v1.full+json");
    map.put("User-Agent", "Future Studio Debug");
else {  
    map.put("Accept", "application/json");
    map.put("Accept-Charset", "utf-8");
    map.put("User-Agent", "Future Studio Release");

Call<List<Task>> call = taskService.getTasks(map);  
// Use it like any other Retrofit call


In this blog post, you've learned how you can use the new @HeaderMap annotation to add a dynamic amount of request headers during runtime. This is a fantastic extension of the previous options for request headers. We love it!

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.