diff --git a/taxii2client/__init__.py b/taxii2client/__init__.py
index b4b0646..5c359cf 100644
--- a/taxii2client/__init__.py
+++ b/taxii2client/__init__.py
@@ -178,7 +178,7 @@ class Status(_TAXIIEndpoint):
     # aren't other endpoints to call on the Status object.
 
     def __init__(self, url, conn=None, user=None, password=None, verify=True,
-                 **kwargs):
+                 status_info=None):
         """Create an API root resource endpoint.
 
         Args:
@@ -187,11 +187,16 @@ class Status(_TAXIIEndpoint):
             password (str): password for authentication (optional)
             conn (_HTTPConnection): reuse connection object, as an alternative
                 to providing username/password
+            status_info (dict): Parsed JSON representing a response from the
+                status endpoint, if already known.  If not given, the
+                endpoint will be queried. (optional)
 
         """
         super(Status, self).__init__(url, conn, user, password, verify)
-        if kwargs:
-            self._populate_fields(**kwargs)
+        self.__raw = None
+        if status_info:
+            self._populate_fields(**status_info)
+            self.__raw = status_info
         else:
             self.refresh()
 
@@ -200,9 +205,14 @@ class Status(_TAXIIEndpoint):
 
     __bool__ = __nonzero__
 
+    @property
+    def _raw(self):
+        """Get the "raw" status response (parsed JSON)."""
+        return self.__raw
+
     def refresh(self, accept=MEDIA_TYPE_TAXII_V20):
         """Updates Status information"""
-        response = self._conn.get(self.url, accept=accept)
+        response = self.__raw = self._conn.get(self.url, accept=accept)
         self._populate_fields(**response)
 
     def wait_until_final(self, poll_interval=1, timeout=60):
@@ -317,7 +327,7 @@ class Collection(_TAXIIEndpoint):
     """
 
     def __init__(self, url, conn=None, user=None, password=None, verify=True,
-                 **kwargs):
+                 collection_info=None):
         """
         Initialize a new Collection.  Either user/password or conn may be
         given, but not both.  The latter is intended for internal use, when
@@ -334,20 +344,22 @@ class Collection(_TAXIIEndpoint):
                 case it must be a path to a CA bundle to use. Defaults to
                 `True` (optional)
             conn (_HTTPConnection): A connection to reuse (optional)
-            kwargs: Collection metadata, if known in advance (optional)
+            collection_info: Collection metadata, if known in advance (optional)
 
         """
 
         super(Collection, self).__init__(url, conn, user, password, verify)
 
         self._loaded = False
+        self.__raw = None
 
         # Since the API Root "Get Collections" endpoint returns information on
         # all collections as a list, it's possible that we can create multiple
         # Collection objects from a single HTTPS request, and not need to call
         # `refresh` for each one.
-        if kwargs:
-            self._populate_fields(**kwargs)
+        if collection_info:
+            self._populate_fields(**collection_info)
+            self.__raw = collection_info
             self._loaded = True
 
     @property
@@ -384,6 +396,12 @@ class Collection(_TAXIIEndpoint):
     def objects_url(self):
         return self.url + "objects/"
 
+    @property
+    def _raw(self):
+        """Get the "raw" collection information response (parsed JSON)."""
+        self._ensure_loaded()
+        return self.__raw
+
     def _populate_fields(self, id=None, title=None, description=None,
                          can_read=None, can_write=None, media_types=None):
         self._id = id  # required
@@ -434,7 +452,7 @@ class Collection(_TAXIIEndpoint):
 
     def refresh(self, accept=MEDIA_TYPE_TAXII_V20):
         """Update Collection information"""
-        response = self._conn.get(self.url, accept=accept)
+        response = self.__raw = self._conn.get(self.url, accept=accept)
         self._populate_fields(**response)
         self._loaded = True
 
@@ -514,7 +532,8 @@ class Collection(_TAXIIEndpoint):
             "../../status/{}".format(status_json["id"])
         )
 
-        status = Status(url=status_url, conn=self._conn, **status_json)
+        status = Status(url=status_url, conn=self._conn,
+                        status_info=status_json)
 
         if not wait_for_completion or status.status == "complete":
             return status
@@ -564,6 +583,7 @@ class ApiRoot(_TAXIIEndpoint):
 
         self._loaded_collections = False
         self._loaded_information = False
+        self.__raw = None
 
     @property
     def collections(self):
@@ -591,6 +611,12 @@ class ApiRoot(_TAXIIEndpoint):
         self._ensure_loaded_information()
         return self._max_content_length
 
+    @property
+    def _raw(self):
+        """Get the "raw" API root information response (parsed JSON)."""
+        self._ensure_loaded_information()
+        return self.__raw
+
     def _ensure_loaded_information(self):
         if not self._loaded_information:
             self.refresh_information()
@@ -620,7 +646,7 @@ class ApiRoot(_TAXIIEndpoint):
 
         This invokes the ``Get API Root Information`` endpoint.
         """
-        response = self._conn.get(self.url, accept=accept)
+        response = self.__raw = self._conn.get(self.url, accept=accept)
 
         self._title = response.get("title")  # required
         self._description = response.get("description")  # optional
@@ -641,7 +667,8 @@ class ApiRoot(_TAXIIEndpoint):
         self._collections = []
         for item in response.get("collections", []):  # optional
             collection_url = url + item["id"] + "/"
-            collection = Collection(collection_url, conn=self._conn, **item)
+            collection = Collection(collection_url, conn=self._conn,
+                                    collection_info=item)
             self._collections.append(collection)
 
         self._loaded_collections = True
@@ -649,7 +676,7 @@ class ApiRoot(_TAXIIEndpoint):
     def get_status(self, status_id, accept=MEDIA_TYPE_TAXII_V20):
         status_url = self.url + "status/" + status_id + "/"
         response = self._conn.get(status_url, accept=accept)
-        return Status(status_url, conn=self._conn, **response)
+        return Status(status_url, conn=self._conn, status_info=response)
 
 
 class Server(_TAXIIEndpoint):
@@ -685,6 +712,7 @@ class Server(_TAXIIEndpoint):
         self._password = password
         self._verify = verify
         self._loaded = False
+        self.__raw = None
 
     @property
     def title(self):
@@ -711,6 +739,12 @@ class Server(_TAXIIEndpoint):
         self._ensure_loaded()
         return self._api_roots
 
+    @property
+    def _raw(self):
+        """Get the "raw" server discovery response (parsed JSON)."""
+        self._ensure_loaded()
+        return self.__raw
+
     def _ensure_loaded(self):
         if not self._loaded:
             self.refresh()
@@ -724,7 +758,8 @@ class Server(_TAXIIEndpoint):
 
     def refresh(self):
         """Update the Server information and list of API Roots"""
-        response = self._conn.get(self.url, accept=MEDIA_TYPE_TAXII_V20)
+        response = self.__raw = self._conn.get(self.url,
+                                               accept=MEDIA_TYPE_TAXII_V20)
 
         self._title = response.get("title")  # required
         self._description = response.get("description")  # optional

Provide access to raw TAXII responses
This can probably be behind some sort of "private" interface (like `_raw`), but it would be helpful to have access to the raw JSON bodies on returned responses.
diff --git a/taxii2client/test/test_client.py b/taxii2client/test/test_client.py
index 5d70679..0505ec4 100644
--- a/taxii2client/test/test_client.py
+++ b/taxii2client/test/test_client.py
@@ -272,11 +272,21 @@ def set_discovery_response(response):
                   content_type=MEDIA_TYPE_TAXII_V20)
 
 
+def set_collections_response():
+    responses.add(responses.GET, COLLECTIONS_URL, COLLECTIONS_RESPONSE,
+                  status=200, content_type=MEDIA_TYPE_TAXII_V20)
+
+
 def set_collection_response(url=COLLECTION_URL, response=COLLECTION_RESPONSE):
     responses.add(responses.GET, url, response, status=200,
                   content_type=MEDIA_TYPE_TAXII_V20)
 
 
+def set_status_response():
+    responses.add(responses.GET, STATUS_URL, STATUS_RESPONSE,
+                  status=200, content_type=MEDIA_TYPE_TAXII_V20)
+
+
 @responses.activate
 def test_server_discovery(server):
     set_discovery_response(DISCOVERY_RESPONSE)
@@ -296,6 +306,9 @@ def test_server_discovery(server):
     assert api_root._loaded_information is False
     assert api_root._loaded_collections is False
 
+    discovery_dict = json.loads(DISCOVERY_RESPONSE)
+    assert server._raw == discovery_dict
+
 
 @responses.activate
 def test_minimal_discovery_response(server):
@@ -389,8 +402,7 @@ def test_api_root_no_max_content_length(api_root):
 
 @responses.activate
 def test_api_root(api_root):
-    responses.add(responses.GET, API_ROOT_URL, API_ROOT_RESPONSE,
-                  status=200, content_type=MEDIA_TYPE_TAXII_V20)
+    set_api_root_response(API_ROOT_RESPONSE)
 
     assert api_root._loaded_information is False
     assert api_root.title == "Malware Research Group"
@@ -399,11 +411,13 @@ def test_api_root(api_root):
     assert api_root.versions == ["taxii-2.0"]
     assert api_root.max_content_length == 9765625
 
+    apiroot_dict = json.loads(API_ROOT_RESPONSE)
+    assert api_root._raw == apiroot_dict
+
 
 @responses.activate
 def test_api_root_collections(api_root):
-    responses.add(responses.GET, COLLECTIONS_URL, COLLECTIONS_RESPONSE, status=200,
-                  content_type=MEDIA_TYPE_TAXII_V20)
+    set_collections_response()
 
     assert api_root._loaded_collections is False
     assert len(api_root.collections) == 2
@@ -420,6 +434,9 @@ def test_api_root_collections(api_root):
     assert coll.can_write is False
     assert coll.media_types == [MEDIA_TYPE_STIX_V20]
 
+    collection_dict = json.loads(COLLECTION_RESPONSE)
+    assert coll._raw == collection_dict
+
 
 @responses.activate
 def test_collection(collection):
@@ -433,6 +450,9 @@ def test_collection(collection):
     assert collection.can_write is False
     assert collection.media_types == [MEDIA_TYPE_STIX_V20]
 
+    collection_dict = json.loads(COLLECTION_RESPONSE)
+    assert collection._raw == collection_dict
+
 
 def test_collection_unexpected_kwarg():
     with pytest.raises(TypeError):
@@ -481,6 +501,9 @@ def test_add_object_to_collection(writable_collection):
     assert status.failure_count == 0
     assert status.pending_count == 0
 
+    status_dict = json.loads(ADD_OBJECTS_RESPONSE)
+    assert status._raw == status_dict
+
 
 @responses.activate
 def test_add_object_to_collection_dict(writable_collection):
@@ -536,9 +559,8 @@ def test_get_manifest(collection):
 
 
 @responses.activate
-def test_get_status(api_root):
-    responses.add(responses.GET, STATUS_URL, STATUS_RESPONSE,
-                  status=200, content_type=MEDIA_TYPE_TAXII_V20)
+def test_get_status(api_root, status_dict):
+    set_status_response()
 
     status = api_root.get_status(STATUS_ID)
 
@@ -550,6 +572,17 @@ def test_get_status(api_root):
     assert status.pending_count == 2
     assert len(status.pendings) == 2
 
+    assert status._raw == status_dict
+
+
+@responses.activate
+def test_status_raw(status_dict):
+    """Test Status object created directly (not obtained via ApiRoot),
+    and _raw property."""
+    set_status_response()
+    status = Status(STATUS_URL)
+    assert status_dict == status._raw
+
 
 @responses.activate
 def test_content_type_valid(collection):
@@ -675,7 +708,8 @@ def test_status_missing_id_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("id")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'id' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -684,7 +718,8 @@ def test_status_missing_status_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("status")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'status' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -693,7 +728,8 @@ def test_status_missing_total_count_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("total_count")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'total_count' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -702,7 +738,8 @@ def test_status_missing_success_count_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("success_count")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'success_count' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -711,7 +748,8 @@ def test_status_missing_failure_count_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("failure_count")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'failure_count' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -720,7 +758,8 @@ def test_status_missing_pending_count_property(status_dict):
     with pytest.raises(ValidationError) as excinfo:
         status_dict.pop("pending_count")
         Status("https://example.com/api1/status/12345678-1234-1234-1234-123456789012/",
-               user="foo", password="bar", verify=False, **status_dict)
+               user="foo", password="bar", verify=False,
+               status_info=status_dict)
 
     assert "No 'pending_count' in Status for request 'https://example.com/api1/status/12345678-1234-1234-1234-123456789012/'" == str(excinfo.value)
 
@@ -729,7 +768,8 @@ def test_collection_missing_id_property(collection_dict):
     with pytest.raises(ValidationError) as excinfo:
         collection_dict.pop("id")
         Collection("https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/",
-                   user="foo", password="bar", verify=False, **collection_dict)
+                   user="foo", password="bar", verify=False,
+                   collection_info=collection_dict)
 
     assert "No 'id' in Collection for request 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'" == str(excinfo.value)
 
@@ -738,7 +778,8 @@ def test_collection_missing_title_property(collection_dict):
     with pytest.raises(ValidationError) as excinfo:
         collection_dict.pop("title")
         Collection("https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/",
-                   user="foo", password="bar", verify=False, **collection_dict)
+                   user="foo", password="bar", verify=False,
+                   collection_info=collection_dict)
 
     assert "No 'title' in Collection for request 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'" == str(excinfo.value)
 
@@ -747,7 +788,8 @@ def test_collection_missing_can_read_property(collection_dict):
     with pytest.raises(ValidationError) as excinfo:
         collection_dict.pop("can_read")
         Collection("https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/",
-                   user="foo", password="bar", verify=False, **collection_dict)
+                   user="foo", password="bar", verify=False,
+                   collection_info=collection_dict)
 
     assert "No 'can_read' in Collection for request 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'" == str(excinfo.value)
 
@@ -756,6 +798,7 @@ def test_collection_missing_can_write_property(collection_dict):
     with pytest.raises(ValidationError) as excinfo:
         collection_dict.pop("can_write")
         Collection("https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/",
-                   user="foo", password="bar", verify=False, **collection_dict)
+                   user="foo", password="bar", verify=False,
+                   collection_info=collection_dict)
 
     assert "No 'can_write' in Collection for request 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'" == str(excinfo.value)

pip install -e .[docs,test]
parse_log_pytest
requirements.txt
coverage pytest pytest-cov responses tox
apt-get update apt-get install -y gcc
3.6
dev-requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs==22.2.0
Babel==2.11.0
bumpversion==0.5.3
certifi==2021.5.30
charset-normalizer==2.0.12
coverage==6.2
distlib==0.3.9
docutils==0.18.1
filelock==3.4.1
idna==3.10
imagesize==1.4.1
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
Jinja2==3.0.3
MarkupSafe==2.0.1
packaging==21.3
platformdirs==2.4.0
pluggy==1.0.0
py==1.11.0
Pygments==2.14.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
pytz==2025.2
requests==2.27.1
responses==0.17.0
six==1.17.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
-e git+https://github.com/oasis-open/cti-taxii-client.git@590746cc70a01bdda74032b8c3feb8d3f0532464#egg=taxii2_client
toml==0.10.2
tomli==1.2.3
tox==3.28.0
typing_extensions==4.1.1
urllib3==1.26.20
virtualenv==20.17.1
zipp==3.6.0

name: cti-taxii-client
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
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - 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=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - bumpversion==0.5.3
      - charset-normalizer==2.0.12
      - coverage==6.2
      - distlib==0.3.9
      - docutils==0.18.1
      - filelock==3.4.1
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - jinja2==3.0.3
      - markupsafe==2.0.1
      - packaging==21.3
      - platformdirs==2.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - pytz==2025.2
      - requests==2.27.1
      - responses==0.17.0
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - toml==0.10.2
      - tomli==1.2.3
      - tox==3.28.0
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - virtualenv==20.17.1
      - zipp==3.6.0
prefix: /opt/conda/envs/cti-taxii-client

taxii2client/test/test_client.py::test_server_discovery taxii2client/test/test_client.py::test_api_root taxii2client/test/test_client.py::test_api_root_collections taxii2client/test/test_client.py::test_collection taxii2client/test/test_client.py::test_add_object_to_collection taxii2client/test/test_client.py::test_get_status taxii2client/test/test_client.py::test_status_raw taxii2client/test/test_client.py::test_status_missing_id_property taxii2client/test/test_client.py::test_status_missing_status_property taxii2client/test/test_client.py::test_status_missing_total_count_property taxii2client/test/test_client.py::test_status_missing_success_count_property taxii2client/test/test_client.py::test_status_missing_failure_count_property taxii2client/test/test_client.py::test_status_missing_pending_count_property taxii2client/test/test_client.py::test_collection_missing_id_property taxii2client/test/test_client.py::test_collection_missing_title_property taxii2client/test/test_client.py::test_collection_missing_can_read_property taxii2client/test/test_client.py::test_collection_missing_can_write_property
taxii2client/test/test_client.py::test_minimal_discovery_response taxii2client/test/test_client.py::test_discovery_with_no_default taxii2client/test/test_client.py::test_discovery_with_no_title taxii2client/test/test_client.py::test_api_root_no_title taxii2client/test/test_client.py::test_api_root_no_versions taxii2client/test/test_client.py::test_api_root_no_max_content_length taxii2client/test/test_client.py::test_collection_unexpected_kwarg taxii2client/test/test_client.py::test_get_collection_objects taxii2client/test/test_client.py::test_get_object taxii2client/test/test_client.py::test_cannot_write_to_readonly_collection taxii2client/test/test_client.py::test_add_object_to_collection_dict taxii2client/test/test_client.py::test_add_object_rases_error_when_collection_id_does_not_match_url taxii2client/test/test_client.py::test_cannot_read_from_writeonly_collection taxii2client/test/test_client.py::test_get_manifest taxii2client/test/test_client.py::test_content_type_valid taxii2client/test/test_client.py::test_content_type_invalid taxii2client/test/test_client.py::test_url_filter_type taxii2client/test/test_client.py::test_filter_id taxii2client/test/test_client.py::test_filter_version taxii2client/test/test_client.py::test_filter_added_after taxii2client/test/test_client.py::test_filter_combo taxii2client/test/test_client.py::test_params_filter_unknown taxii2client/test/test_client.py::test_taxii_endpoint_raises_exception taxii2client/test/test_client.py::test_valid_content_type_for_connection taxii2client/test/test_client.py::test_invalid_content_type_for_connection
taxii2client/__init__.py
taxii2client/__init__.py