diff --git a/recurly/pager.py b/recurly/pager.py
index 1102023..02d6d8b 100644
--- a/recurly/pager.py
+++ b/recurly/pager.py
@@ -82,7 +82,7 @@ class Pager:
         """Makes a HEAD request to the API to determine how many total records exist.
         """
         resource = self.__client._make_request("HEAD", self.__path, None, self.__params)
-        return int(resource.get_response().total_records)
+        return resource.get_response().total_records
 
     def __map_array_params(self, params):
         """Converts array parameters to CSV strings to maintain consistency with
diff --git a/recurly/response.py b/recurly/response.py
index a850c51..c42ee80 100644
--- a/recurly/response.py
+++ b/recurly/response.py
@@ -1,7 +1,28 @@
-import sys, traceback
 from datetime import datetime
 import recurly
-import json
+
+
+def parse_int_header(dictionary, key):
+    """Defensively parse an int header"""
+    val = dictionary.get(key)
+
+    if val is None or not isinstance(val, str):
+        return None
+
+    if not val.isdigit():
+        return None
+
+    return int(val)
+
+
+def parse_datetime_header(dictionary, key):
+    """Defensively parse datetime header"""
+
+    int_val = parse_int_header(dictionary, key)
+    if int_val is None:
+        return None
+
+    return datetime.utcfromtimestamp(int_val)
 
 
 class Response:
@@ -12,29 +33,26 @@ class Response:
         self.status = response.status
         http_body = response.read()
         self.body = None
+        self.__headers = response.headers
+
+        self.request_id = self.__headers.get("X-Request-Id")
+        self.date = self.__headers.get("Date")
+
+        self.rate_limit = parse_int_header(self.__headers, "X-RateLimit-Limit")
+        self.rate_limit_remaining = parse_int_header(
+            self.__headers, "X-RateLimit-Remaining"
+        )
+        self.rate_limit_reset = parse_datetime_header(
+            self.__headers, "X-RateLimit-Reset"
+        )
+        self.content_type = self.__headers.get("Content-Type", "").split(";")[0]
+
+        self.proxy_metadata = {
+            "server": self.__headers.get("Server"),
+            "cf-ray": self.__headers.get("CF-RAY"),
+        }
+
+        self.total_records = parse_int_header(self.__headers, "Recurly-Total-Records")
 
-        try:
-            self.__headers = response.headers
-            self.request_id = self.__headers.get("X-Request-Id")
-            self.rate_limit = int(self.__headers.get("X-RateLimit-Limit"))
-            self.rate_limit_remaining = int(self.__headers.get("X-RateLimit-Remaining"))
-            self.rate_limit_reset = datetime.utcfromtimestamp(
-                int(self.__headers.get("X-RateLimit-Reset"))
-            )
-            self.date = self.__headers.get("Date")
-            self.content_type = self.__headers.get("Content-Type", "").split(";")[0]
-            self.proxy_metadata = {
-                "server": self.__headers.get("Server"),
-                "cf-ray": self.__headers.get("CF-RAY"),
-            }
-            self.total_records = self.__headers.get("recurly-total-records")
-            if http_body and len(http_body) > 0:
-                self.body = http_body
-        except:
-            # Re-raise the exception in strict-mode
-            if recurly.STRICT_MODE:
-                raise
-            # Log and ignore it in production, we don't want this to kill the whole request
-            else:
-                print("[WARNING][Recurly] Unexpected error parsing response metadata")
-                traceback.print_exc(file=sys.stdout)
+        if http_body and len(http_body) > 0:
+            self.body = http_body

RateLimiter Exception 
When I reach the rate-limit I get a no-explicit error message.

The error that I get is the following:
`
self.rate_limit = int(self.__headers.get("X-RateLimit-Limit"))
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
`

**Your Environment**

- 3.4.2
- python3.8

diff --git a/tests/test_resource.py b/tests/test_resource.py
index 882d4bc..3abaa88 100644
--- a/tests/test_resource.py
+++ b/tests/test_resource.py
@@ -28,46 +28,6 @@ class TestResource(unittest.TestCase):
         with self.assertRaises(ValueError):
             self.assertEqual(cast(obj), obj)
 
-    def test_cast_from_response(self):
-        resp = MagicMock()
-        resp.headers = {
-            "X-Request-Id": "0av50sm5l2n2gkf88ehg",
-            "X-RateLimit-Limit": "2000",
-            "X-RateLimit-Remaining": "1985",
-            "X-RateLimit-Reset": "1564624560",
-            "Date": "Thu, 01 Aug 2019 01:26:44 GMT",
-            "Server": "cloudflare",
-            "CF-RAY": "4ff4b71268424738-EWR",
-        }
-
-        request = Request("GET", "/sites", {})
-        empty = cast({}, "Empty", Response(resp, request))
-        response = empty.get_response()
-
-        self.assertEqual(type(response), Response)
-        self.assertEqual(response.request_id, "0av50sm5l2n2gkf88ehg")
-        self.assertEqual(response.rate_limit, 2000)
-        self.assertEqual(response.rate_limit_remaining, 1985)
-        self.assertEqual(response.rate_limit_reset, datetime(2019, 8, 1, 1, 56))
-        self.assertEqual(response.date, "Thu, 01 Aug 2019 01:26:44 GMT")
-        self.assertEqual(response.proxy_metadata["server"], "cloudflare")
-        self.assertEqual(response.proxy_metadata["cf-ray"], "4ff4b71268424738-EWR")
-        self.assertEqual(response.request.method, "GET")
-        self.assertEqual(response.request.path, "/sites")
-        self.assertEqual(response.request.body, {})
-
-        resp = MagicMock()
-        resp.headers = {
-            "X-Request-Id": "abcd123",
-            "X-RateLimit-Limit": "invalid2000",
-            "X-RateLimit-Remaining": "1985",
-            "X-RateLimit-Reset": "1564624560",
-            "Date": "Thu, 01 Aug 2019 01:26:44 GMT",
-        }
-
-        with self.assertRaises(ValueError):
-            cast({}, "Empty", Response(resp, request))
-
     def test_cast_page(self):
         # should return a page of cast data
         page = cast(
diff --git a/tests/test_response.py b/tests/test_response.py
new file mode 100644
index 0000000..6b83b1d
--- /dev/null
+++ b/tests/test_response.py
@@ -0,0 +1,79 @@
+import unittest
+import recurly
+from datetime import datetime
+from recurly import Response, Request
+from unittest.mock import Mock, MagicMock
+
+
+class TestResponse(unittest.TestCase):
+    def test_init(self):
+        resp = MagicMock()
+        resp.headers = {
+            "X-Request-Id": "0av50sm5l2n2gkf88ehg",
+            "X-RateLimit-Limit": "2000",
+            "X-RateLimit-Remaining": "1985",
+            "X-RateLimit-Reset": "1564624560",
+            "Recurly-Total-Records": "100",
+            "Date": "Thu, 01 Aug 2019 01:26:44 GMT",
+            "Server": "cloudflare",
+            "CF-RAY": "4ff4b71268424738-EWR",
+        }
+
+        req = Request("GET", "/sites", {})
+        response = Response(resp, req)
+
+        self.assertEqual(type(response), Response)
+        self.assertEqual(response.request_id, "0av50sm5l2n2gkf88ehg")
+        self.assertEqual(response.rate_limit, 2000)
+        self.assertEqual(response.rate_limit_remaining, 1985)
+        self.assertEqual(response.rate_limit_reset, datetime(2019, 8, 1, 1, 56))
+        self.assertEqual(response.total_records, 100)
+        self.assertEqual(response.date, "Thu, 01 Aug 2019 01:26:44 GMT")
+        self.assertEqual(response.proxy_metadata["server"], "cloudflare")
+        self.assertEqual(response.proxy_metadata["cf-ray"], "4ff4b71268424738-EWR")
+        self.assertEqual(response.request.method, "GET")
+        self.assertEqual(response.request.path, "/sites")
+        self.assertEqual(response.request.body, {})
+
+    def test_init_with_invalid_headers(self):
+        resp = MagicMock()
+        resp.headers = {
+            "X-Request-Id": "0av50sm5l2n2gkf88ehg",
+            "X-RateLimit-Limit": "notanum",
+            "X-RateLimit-Remaining": "notanum",
+            "X-RateLimit-Reset": "notanum",
+            "recurly-total-records": "notanum",
+            "Date": "Thu, 01 Aug 2019 01:26:44 GMT",
+            "Server": "cloudflare",
+            "CF-RAY": "4ff4b71268424738-EWR",
+        }
+
+        req = Request("GET", "/sites", {})
+        response = Response(resp, req)
+
+        self.assertEqual(type(response), Response)
+        self.assertEqual(response.request_id, "0av50sm5l2n2gkf88ehg")
+        self.assertEqual(response.rate_limit, None)
+        self.assertEqual(response.rate_limit_remaining, None)
+        self.assertEqual(response.rate_limit_reset, None)
+        self.assertEqual(response.total_records, None)
+        self.assertEqual(response.date, "Thu, 01 Aug 2019 01:26:44 GMT")
+        self.assertEqual(response.proxy_metadata["server"], "cloudflare")
+        self.assertEqual(response.proxy_metadata["cf-ray"], "4ff4b71268424738-EWR")
+
+    def test_init_with_missing_headers(self):
+        resp = MagicMock()
+        resp.headers = {}
+
+        req = Request("GET", "/sites", {})
+        response = Response(resp, req)
+
+        self.assertEqual(type(response), Response)
+        self.assertEqual(response.request_id, None)
+        self.assertEqual(response.rate_limit, None)
+        self.assertEqual(response.rate_limit_remaining, None)
+        self.assertEqual(response.rate_limit_reset, None)
+        self.assertEqual(response.total_records, None)
+        self.assertEqual(response.date, None)
+        self.assertEqual(response.proxy_metadata["server"], None)
+        self.assertEqual(response.proxy_metadata["cf-ray"], None)

pip install -e .[dev]
parse_log_pytest
pytest
coverage Sphinx sphinxcontrib-napoleon m2r pytest
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
babel==2.17.0
certifi==2025.1.31
charset-normalizer==3.4.1
coverage==7.8.0
docutils==0.21.2
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.1.6
m2r==0.3.1
MarkupSafe==3.0.2
mistune==0.8.4
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pockets==0.9.1
Pygments==2.19.1
pytest @ file:///croot/pytest_1738938843180/work
-e git+https://github.com/recurly/recurly-client-python.git@69a07d89a68d3d72ad2757c91c23d81034c921c7#egg=recurly
requests==2.32.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-napoleon==0.7
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
urllib3==2.3.0
zipp==3.21.0

name: recurly-client-python
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - babel==2.17.0
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - docutils==0.21.2
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - jinja2==3.1.6
      - m2r==0.3.1
      - markupsafe==3.0.2
      - mistune==0.8.4
      - pockets==0.9.1
      - pygments==2.19.1
      - requests==2.32.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-napoleon==0.7
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - urllib3==2.3.0
      - zipp==3.21.0
prefix: /opt/conda/envs/recurly-client-python

tests/test_response.py::TestResponse::test_init tests/test_response.py::TestResponse::test_init_with_invalid_headers tests/test_response.py::TestResponse::test_init_with_missing_headers
tests/test_resource.py::TestResource::test_cast_object_unknown_class
tests/test_resource.py::TestResource::test_cast tests/test_resource.py::TestResource::test_cast_error tests/test_resource.py::TestResource::test_cast_page tests/test_resource.py::TestResource::test_cast_unknown_error tests/test_resource.py::TestResource::test_repr_str
recurly/pager.py recurly/response.py
recurly/pager.py recurly/response.py