diff --git a/docs/source/dev/types.rst b/docs/source/dev/types.rst
index dafa258d..f9314f14 100644
--- a/docs/source/dev/types.rst
+++ b/docs/source/dev/types.rst
@@ -62,3 +62,8 @@ Url
 ===
 
 .. autoclass:: uplink.Url
+
+Timeout
+=======
+
+.. autoclass:: uplink.Timeout
diff --git a/tests/unit/test_arguments.py b/tests/unit/test_arguments.py
index 555e34c5..826fcd62 100644
--- a/tests/unit/test_arguments.py
+++ b/tests/unit/test_arguments.py
@@ -424,3 +424,12 @@ def test_modify_request_definition_failure(
     def test_modify_request(self, request_builder):
         arguments.Url().modify_request(request_builder, "/some/path")
         assert request_builder.url == "/some/path"
+
+
+class TestTimeout(ArgumentTestCase, FuncDecoratorTestCase):
+    type_cls = arguments.Timeout
+    expected_converter_key = keys.Identity()
+
+    def test_modify_request(self, request_builder):
+        arguments.Timeout().modify_request(request_builder, 10)
+        assert request_builder.info["timeout"] == 10
diff --git a/tests/unit/test_converters.py b/tests/unit/test_converters.py
index b269fa0c..32d5509b 100644
--- a/tests/unit/test_converters.py
+++ b/tests/unit/test_converters.py
@@ -312,6 +312,37 @@ def test_eq(self):
         assert not (converters.keys.Sequence(1) == 1)
 
 
+class TestIdentity(object):
+    _sentinel = object()
+
+    @pytest.fixture(scope="class")
+    def registry(self):
+        return converters.ConverterFactoryRegistry(
+            (converters.StandardConverter(),)
+        )
+
+    @pytest.fixture(scope="class")
+    def key(self):
+        return converters.keys.Identity()
+
+    @pytest.mark.parametrize(
+        "value, expected",
+        [
+            (1, 1),
+            ("a", "a"),
+            (_sentinel, _sentinel),
+            ({"a": "b"}, {"a": "b"}),
+            ([1, 2], [1, 2]),
+        ],
+    )
+    def test_convert(self, registry, key, value, expected):
+        converter = registry[key]()
+        assert converter(value) == expected
+
+    def test_eq(self):
+        assert converters.keys.Identity() == converters.keys.Identity()
+
+
 class TestRegistry(object):
     @pytest.mark.parametrize(
         "converter",
diff --git a/uplink/__init__.py b/uplink/__init__.py
index 62dc55b9..9e8ec9cb 100644
--- a/uplink/__init__.py
+++ b/uplink/__init__.py
@@ -40,6 +40,7 @@
     PartMap,
     Body,
     Url,
+    Timeout,
 )
 from uplink.ratelimit import ratelimit
 from uplink.retry import retry
@@ -88,6 +89,7 @@
     "PartMap",
     "Body",
     "Url",
+    "Timeout",
     "retry",
     "ratelimit",
 ]
diff --git a/uplink/arguments.py b/uplink/arguments.py
index 8e095b3e..1e7e7e79 100644
--- a/uplink/arguments.py
+++ b/uplink/arguments.py
@@ -23,6 +23,7 @@
     "PartMap",
     "Body",
     "Url",
+    "Timeout",
 ]
 
 
@@ -675,3 +676,35 @@ def modify_request_definition(self, request_definition_builder):
     def _modify_request(cls, request_builder, value):
         """Updates request url."""
         request_builder.url = value
+
+
+class Timeout(FuncDecoratorMixin, ArgumentAnnotation):
+    """
+    Pass a timeout as a method argument at runtime.
+
+    While :py:class:`uplink.timeout` attaches static timeout to all requests
+    sent from a consumer method, this class turns a method argument into a
+    dynamic timeout value.
+
+    Example:
+        .. code-block:: python
+
+            @get("/user/posts")
+            def get_posts(self, timeout: Timeout() = 60):
+                \"""Fetch all posts for the current users giving up after given
+                number of seconds.\"""
+
+    """
+
+    @property
+    def type(self):
+        return float
+
+    @property
+    def converter_key(self):
+        """Do not convert passed argument."""
+        return keys.Identity()
+
+    def _modify_request(self, request_builder, value):
+        """Modifies request timeout."""
+        request_builder.info["timeout"] = value
diff --git a/uplink/converters/keys.py b/uplink/converters/keys.py
index 09c07e84..c9142372 100644
--- a/uplink/converters/keys.py
+++ b/uplink/converters/keys.py
@@ -86,3 +86,21 @@ def convert(self, converter, value):
             return list(map(converter, value))
         else:
             return converter(value)
+
+
+class Identity(object):
+    """
+    Identity conversion - pass value as is
+    """
+
+    def __call__(self, converter_registry):
+        return self._identity_factory
+
+    def __eq__(self, other):
+        return type(other) is type(self)
+
+    def _identity_factory(self, *args, **kwargs):
+        return self._identity
+
+    def _identity(self, value):
+        return value