diff --git a/dydx3/__init__.py b/dydx3/__init__.py
index e4d990d..5a6e168 100644
--- a/dydx3/__init__.py
+++ b/dydx3/__init__.py
@@ -1,4 +1,4 @@
-from dydx3.dydx_client import Client
+from dydx3.dydx_client import Client, TorClient
 from dydx3.errors import DydxError
 from dydx3.errors import DydxApiError
 from dydx3.errors import TransactionReverted
diff --git a/dydx3/dydx_client.py b/dydx3/dydx_client.py
index 204146d..45b580b 100644
--- a/dydx3/dydx_client.py
+++ b/dydx3/dydx_client.py
@@ -3,6 +3,7 @@
 from dydx3.constants import NETWORK_ID_MAINNET
 from dydx3.eth_signing import SignWithWeb3
 from dydx3.eth_signing import SignWithKey
+from dydx3.helpers.requests import _RequestManager
 from dydx3.modules.api_keys import ApiKeys
 from dydx3.modules.eth import Eth
 from dydx3.modules.private import Private
@@ -14,12 +15,12 @@
 )
 
 
-class Client(object):
+class Client(_RequestManager):
 
     def __init__(
         self,
         host,
-        api_timeout=3000,  # TODO: Actually use this.
+        api_timeout=3000,
         default_ethereum_address=None,
         eth_private_key=None,
         eth_send_options=None,
@@ -73,7 +74,12 @@ def __init__(
 
         # Initialize the public module. Other modules are initialized on
         # demand, if the necessary configuration options were provided.
+
+        self._set_session()
+
         self._public = Public(host)
+        self._public._session = self._session
+        self._public.api_timeout = self.api_timeout
         self._private = None
         self._api_keys = None
         self._eth = None
@@ -140,6 +146,8 @@ def private(self):
                     default_address=self.default_address,
                     api_key_credentials=self.api_key_credentials,
                 )
+                self._private._session = self._session
+                self._private.api_timeout = self.api_timeout
             else:
                 raise Exception(
                     'Private endpoints not supported ' +
@@ -161,6 +169,8 @@ def api_keys(self):
                     network_id=self.network_id,
                     default_address=self.default_address,
                 )
+                self._api_keys._session = self._session
+                self._api_keys.api_timeout = self.api_timeout
             else:
                 raise Exception(
                     'API keys module is not supported since no Ethereum ' +
@@ -187,6 +197,8 @@ def onboarding(self):
                         self.stark_public_key_y_coordinate
                     ),
                 )
+                self._onboarding._session = self._session
+                self._onboarding.api_timeout = self.api_timeout
             else:
                 raise Exception(
                     'Onboarding is not supported since no Ethereum ' +
@@ -218,3 +230,13 @@ def eth(self):
                     'eth_private_key nor web3_account was provided',
                 )
         return self._eth
+
+
+class TorClient(Client):
+
+    def _set_session(self):
+        super()._set_session()
+        self._session.proxies = {
+            'http':  'socks5://127.0.0.1:9050',
+            'https': 'socks5://127.0.0.1:9050'
+            }
diff --git a/dydx3/helpers/requests.py b/dydx3/helpers/requests.py
index bca9e07..66d88a4 100644
--- a/dydx3/helpers/requests.py
+++ b/dydx3/helpers/requests.py
@@ -5,28 +5,38 @@
 from dydx3.errors import DydxApiError
 from dydx3.helpers.request_helpers import remove_nones
 
-# TODO: Use a separate session per client instance.
-session = requests.session()
-session.headers.update({
-    'Accept': 'application/json',
-    'Content-Type': 'application/json',
-    'User-Agent': 'dydx/python',
-})
-
-
-def request(uri, method, headers=None, data_values={}):
-    response = send_request(
-        uri,
-        method,
-        headers,
-        data=json.dumps(
-            remove_nones(data_values)
-        )
-    )
-    if not str(response.status_code).startswith('2'):
-        raise DydxApiError(response)
-    return response.json() if response.content else '{}'
+requests.get
+
+class _RequestManager:
+
+    _session = None
+    api_timeout = None
 
+    def _set_session(self):
+        self._session = requests.session()
+        self._session.headers.update({
+            'Accept': 'application/json',
+            'Content-Type': 'application/json',
+            'User-Agent': 'dydx/python',
+        })
+
+    def request(self, uri, method, headers=None, data_values={}):
+        response = self.send_request(
+            uri,
+            method,
+            headers,
+            data=json.dumps(
+                remove_nones(data_values)
+            ),
+            timeout=self.api_timeout
+        )
+        if not str(response.status_code).startswith('2'):
+            raise DydxApiError(response)
+        if response.content:
+            return response.json()
+        return '{}'
 
-def send_request(uri, method, headers=None, **kwargs):
-    return getattr(session, method)(uri, headers=headers, **kwargs)
+    def send_request(self, uri, method, headers=None, **kwargs):
+        if not _RequestManager._session:
+            self._set_session()
+        return getattr(self._session, method)(uri, headers=headers, **kwargs)
diff --git a/dydx3/modules/api_keys.py b/dydx3/modules/api_keys.py
index eb9d2cf..2c65d59 100644
--- a/dydx3/modules/api_keys.py
+++ b/dydx3/modules/api_keys.py
@@ -2,10 +2,10 @@
 from dydx3.helpers.request_helpers import generate_query_path
 from dydx3.helpers.request_helpers import json_stringify
 from dydx3.eth_signing import SignApiKeyAction
-from dydx3.helpers.requests import request
+from dydx3.helpers.requests import _RequestManager
 
 
-class ApiKeys(object):
+class ApiKeys(_RequestManager):
     """Module for adding, querying, and deleting API keys."""
 
     def __init__(
@@ -41,7 +41,7 @@ def _request(
             timestamp=timestamp,
         )
 
-        return request(
+        return self.request(
             self.host + request_path,
             method,
             {
diff --git a/dydx3/modules/onboarding.py b/dydx3/modules/onboarding.py
index f0de0a2..468af29 100644
--- a/dydx3/modules/onboarding.py
+++ b/dydx3/modules/onboarding.py
@@ -5,10 +5,10 @@
 from dydx3.constants import OFF_CHAIN_ONBOARDING_ACTION
 from dydx3.constants import OFF_CHAIN_KEY_DERIVATION_ACTION
 from dydx3.eth_signing import SignOnboardingAction
-from dydx3.helpers.requests import request
+from dydx3.helpers.requests import _RequestManager
 
 
-class Onboarding(object):
+class Onboarding(_RequestManager):
 
     def __init__(
         self,
@@ -42,7 +42,7 @@ def _post(
         )
 
         request_path = '/'.join(['/v3', endpoint])
-        return request(
+        return self.request(
             self.host + request_path,
             'post',
             {
diff --git a/dydx3/modules/private.py b/dydx3/modules/private.py
index fecb00b..8a128f7 100644
--- a/dydx3/modules/private.py
+++ b/dydx3/modules/private.py
@@ -15,7 +15,7 @@
 from dydx3.helpers.request_helpers import iso_to_epoch_seconds
 from dydx3.helpers.request_helpers import json_stringify
 from dydx3.helpers.request_helpers import remove_nones
-from dydx3.helpers.requests import request
+from dydx3.helpers.requests import _RequestManager
 from dydx3.starkex.helpers import get_transfer_erc20_fact
 from dydx3.starkex.helpers import nonce_from_client_id
 from dydx3.starkex.order import SignableOrder
@@ -23,7 +23,7 @@
 from dydx3.starkex.conditional_transfer import SignableConditionalTransfer
 
 
-class Private(object):
+class Private(_RequestManager):
 
     def __init__(
         self,
@@ -61,7 +61,7 @@ def _private_request(
             'DYDX-TIMESTAMP': now_iso_string,
             'DYDX-PASSPHRASE': self.api_key_credentials['passphrase'],
         }
-        return request(
+        return self.request(
             self.host + request_path,
             method,
             headers,
diff --git a/dydx3/modules/public.py b/dydx3/modules/public.py
index 35d9842..54c99e3 100644
--- a/dydx3/modules/public.py
+++ b/dydx3/modules/public.py
@@ -1,8 +1,8 @@
 from dydx3.helpers.request_helpers import generate_query_path
-from dydx3.helpers.requests import request
+from dydx3.helpers.requests import _RequestManager
 
 
-class Public(object):
+class Public(_RequestManager):
 
     def __init__(
         self,
@@ -13,13 +13,13 @@ def __init__(
     # ============ Request Helpers ============
 
     def _get(self, request_path, params={}):
-        return request(
+        return self.request(
             generate_query_path(self.host + request_path, params),
             'get',
         )
 
     def _put(self, endpoint, data):
-        return request(
+        return self.request(
             self.host + '/v3/' + endpoint,
             'put',
             {},