diff --git a/swiftclient/client.py b/swiftclient/client.py
index 3d848cd3..e95819f1 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -332,6 +332,25 @@ def get_auth(auth_url, user, key, **kwargs):
                           % auth_version)
 
 
+def store_response(resp, response_dict):
+    """
+    store information about an operation into a dict
+
+    :param resp: an http response object containing the response
+                 headers
+    :param response_dict: a dict into which are placed the
+       status, reason and a dict of lower-cased headers
+    """
+    if response_dict is not None:
+        resp_headers = {}
+        for header, value in resp.getheaders():
+            resp_headers[header.lower()] = value
+
+        response_dict['status'] = resp.status
+        response_dict['reason'] = resp.reason
+        response_dict['headers'] = resp_headers
+
+
 def get_account(url, token, marker=None, limit=None, prefix=None,
                 end_marker=None, http_conn=None, full_listing=False):
     """
@@ -432,7 +451,7 @@ def head_account(url, token, http_conn=None):
     return resp_headers
 
 
-def post_account(url, token, headers, http_conn=None):
+def post_account(url, token, headers, http_conn=None, response_dict=None):
     """
     Update an account's metadata.
 
@@ -441,6 +460,8 @@ def post_account(url, token, headers, http_conn=None):
     :param headers: additional headers to include in the request
     :param http_conn: HTTP connection object (If None, it will create the
                       conn object)
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP POST request failed
     """
     if http_conn:
@@ -453,6 +474,9 @@ def post_account(url, token, headers, http_conn=None):
     resp = conn.getresponse()
     body = resp.read()
     http_log((url, method,), {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Account POST failed',
                               http_scheme=parsed.scheme,
@@ -582,7 +606,8 @@ def head_container(url, token, container, http_conn=None, headers=None):
     return resp_headers
 
 
-def put_container(url, token, container, headers=None, http_conn=None):
+def put_container(url, token, container, headers=None, http_conn=None,
+                  response_dict=None):
     """
     Create a container
 
@@ -592,6 +617,8 @@ def put_container(url, token, container, headers=None, http_conn=None):
     :param headers: additional headers to include in the request
     :param http_conn: HTTP connection object (If None, it will create the
                       conn object)
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP PUT request failed
     """
     if http_conn:
@@ -608,6 +635,9 @@ def put_container(url, token, container, headers=None, http_conn=None):
     conn.request(method, path, '', headers)
     resp = conn.getresponse()
     body = resp.read()
+
+    store_response(resp, response_dict)
+
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), method,),
              {'headers': headers}, resp, body)
     if resp.status < 200 or resp.status >= 300:
@@ -618,7 +648,8 @@ def put_container(url, token, container, headers=None, http_conn=None):
                               http_response_content=body)
 
 
-def post_container(url, token, container, headers, http_conn=None):
+def post_container(url, token, container, headers, http_conn=None,
+                   response_dict=None):
     """
     Update a container's metadata.
 
@@ -628,6 +659,8 @@ def post_container(url, token, container, headers, http_conn=None):
     :param headers: additional headers to include in the request
     :param http_conn: HTTP connection object (If None, it will create the
                       conn object)
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP POST request failed
     """
     if http_conn:
@@ -644,6 +677,9 @@ def post_container(url, token, container, headers, http_conn=None):
     body = resp.read()
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), method,),
              {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Container POST failed',
                               http_scheme=parsed.scheme, http_host=conn.host,
@@ -652,7 +688,8 @@ def post_container(url, token, container, headers, http_conn=None):
                               http_response_content=body)
 
 
-def delete_container(url, token, container, http_conn=None):
+def delete_container(url, token, container, http_conn=None,
+                     response_dict=None):
     """
     Delete a container
 
@@ -661,6 +698,8 @@ def delete_container(url, token, container, http_conn=None):
     :param container: container name to delete
     :param http_conn: HTTP connection object (If None, it will create the
                       conn object)
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP DELETE request failed
     """
     if http_conn:
@@ -675,6 +714,9 @@ def delete_container(url, token, container, http_conn=None):
     body = resp.read()
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), method,),
              {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Container DELETE failed',
                               http_scheme=parsed.scheme, http_host=conn.host,
@@ -684,7 +726,8 @@ def delete_container(url, token, container, http_conn=None):
 
 
 def get_object(url, token, container, name, http_conn=None,
-               resp_chunk_size=None, query_string=None):
+               resp_chunk_size=None, query_string=None,
+               response_dict=None):
     """
     Get an object
 
@@ -699,6 +742,8 @@ def get_object(url, token, container, name, http_conn=None,
                             the object's contents before making another
                             request.
     :param query_string: if set will be appended with '?' to generated path
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :returns: a tuple of (response headers, the object's contents) The response
               headers will be a dict and all header names will be lowercase.
     :raises ClientException: HTTP GET request failed
@@ -714,6 +759,12 @@ def get_object(url, token, container, name, http_conn=None,
     headers = {'X-Auth-Token': token}
     conn.request(method, path, '', headers)
     resp = conn.getresponse()
+
+    parsed_response = {}
+    store_response(resp, parsed_response)
+    if response_dict is not None:
+        response_dict.update(parsed_response)
+
     if resp.status < 200 or resp.status >= 300:
         body = resp.read()
         http_log(('%s%s' % (url.replace(parsed.path, ''), path), method,),
@@ -733,12 +784,10 @@ def get_object(url, token, container, name, http_conn=None,
         object_body = _object_body()
     else:
         object_body = resp.read()
-    resp_headers = {}
-    for header, value in resp.getheaders():
-        resp_headers[header.lower()] = value
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), method,),
              {'headers': headers}, resp, None)
-    return resp_headers, object_body
+
+    return parsed_response['headers'], object_body
 
 
 def head_object(url, token, container, name, http_conn=None):
@@ -782,7 +831,7 @@ def head_object(url, token, container, name, http_conn=None):
 def put_object(url, token=None, container=None, name=None, contents=None,
                content_length=None, etag=None, chunk_size=None,
                content_type=None, headers=None, http_conn=None, proxy=None,
-               query_string=None):
+               query_string=None, response_dict=None):
     """
     Put an object
 
@@ -811,7 +860,9 @@ def put_object(url, token=None, container=None, name=None, contents=None,
     :param proxy: proxy to connect through, if any; None by default; str of the
                   format 'http://127.0.0.1:8888' to set one
     :param query_string: if set will be appended with '?' to generated path
-    :returns: etag from server response
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
+    :returns: etag
     :raises ClientException: HTTP PUT request failed
     """
     if http_conn:
@@ -878,16 +929,21 @@ def put_object(url, token=None, container=None, name=None, contents=None,
     headers = {'X-Auth-Token': token}
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), 'PUT',),
              {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Object PUT failed', http_scheme=parsed.scheme,
                               http_host=conn.host, http_port=conn.port,
                               http_path=path, http_status=resp.status,
                               http_reason=resp.reason,
                               http_response_content=body)
+
     return resp.getheader('etag', '').strip('"')
 
 
-def post_object(url, token, container, name, headers, http_conn=None):
+def post_object(url, token, container, name, headers, http_conn=None,
+                response_dict=None):
     """
     Update object metadata
 
@@ -898,6 +954,8 @@ def post_object(url, token, container, name, headers, http_conn=None):
     :param headers: additional headers to include in the request
     :param http_conn: HTTP connection object (If None, it will create the
                       conn object)
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP POST request failed
     """
     if http_conn:
@@ -911,6 +969,9 @@ def post_object(url, token, container, name, headers, http_conn=None):
     body = resp.read()
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), 'POST',),
              {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Object POST failed', http_scheme=parsed.scheme,
                               http_host=conn.host, http_port=conn.port,
@@ -920,7 +981,8 @@ def post_object(url, token, container, name, headers, http_conn=None):
 
 
 def delete_object(url, token=None, container=None, name=None, http_conn=None,
-                  headers=None, proxy=None, query_string=None):
+                  headers=None, proxy=None, query_string=None,
+                  response_dict=None):
     """
     Delete object
 
@@ -936,6 +998,8 @@ def delete_object(url, token=None, container=None, name=None, http_conn=None,
     :param proxy: proxy to connect through, if any; None by default; str of the
                   format 'http://127.0.0.1:8888' to set one
     :param query_string: if set will be appended with '?' to generated path
+    :param response_dict: an optional dictionary into which to place
+                     the response - status, reason and headers
     :raises ClientException: HTTP DELETE request failed
     """
     if http_conn:
@@ -960,6 +1024,9 @@ def delete_object(url, token=None, container=None, name=None, http_conn=None,
     body = resp.read()
     http_log(('%s%s' % (url.replace(parsed.path, ''), path), 'DELETE',),
              {'headers': headers}, resp, body)
+
+    store_response(resp, response_dict)
+
     if resp.status < 200 or resp.status >= 300:
         raise ClientException('Object DELETE failed',
                               http_scheme=parsed.scheme, http_host=conn.host,
@@ -1032,10 +1099,20 @@ class Connection(object):
         return http_connection(self.url,
                                ssl_compression=self.ssl_compression)
 
+    def _add_response_dict(self, target_dict, kwargs):
+        if target_dict is not None:
+            response_dict = kwargs['response_dict']
+            if 'response_dicts' in target_dict:
+                target_dict['response_dicts'].append(response_dict)
+            else:
+                target_dict['response_dicts'] = [response_dict]
+            target_dict.update(response_dict)
+
     def _retry(self, reset_func, func, *args, **kwargs):
         self.attempts = 0
         retried_auth = False
         backoff = self.starting_backoff
+        caller_response_dict = kwargs.pop('response_dict', None)
         while self.attempts <= self.retries:
             self.attempts += 1
             try:
@@ -1045,13 +1122,18 @@ class Connection(object):
                 if not self.http_conn:
                     self.http_conn = self.http_connection()
                 kwargs['http_conn'] = self.http_conn
+                if caller_response_dict is not None:
+                    kwargs['response_dict'] = {}
                 rv = func(self.url, self.token, *args, **kwargs)
+                self._add_response_dict(caller_response_dict, kwargs)
                 return rv
             except (socket.error, HTTPException):
+                self._add_response_dict(caller_response_dict, kwargs)
                 if self.attempts > self.retries:
                     raise
                 self.http_conn = None
             except ClientException as err:
+                self._add_response_dict(caller_response_dict, kwargs)
                 if self.attempts > self.retries:
                     raise
                 if err.http_status == 401:
@@ -1086,9 +1168,10 @@ class Connection(object):
                            prefix=prefix, end_marker=end_marker,
                            full_listing=full_listing)
 
-    def post_account(self, headers):
+    def post_account(self, headers, response_dict=None):
         """Wrapper for :func:`post_account`"""
-        return self._retry(None, post_account, headers)
+        return self._retry(None, post_account, headers,
+                           response_dict=response_dict)
 
     def head_container(self, container):
         """Wrapper for :func:`head_container`"""
@@ -1106,32 +1189,36 @@ class Connection(object):
                            end_marker=end_marker, path=path,
                            full_listing=full_listing)
 
-    def put_container(self, container, headers=None):
+    def put_container(self, container, headers=None, response_dict=None):
         """Wrapper for :func:`put_container`"""
-        return self._retry(None, put_container, container, headers=headers)
+        return self._retry(None, put_container, container, headers=headers,
+                           response_dict=response_dict)
 
-    def post_container(self, container, headers):
+    def post_container(self, container, headers, response_dict=None):
         """Wrapper for :func:`post_container`"""
-        return self._retry(None, post_container, container, headers)
+        return self._retry(None, post_container, container, headers,
+                           response_dict=response_dict)
 
-    def delete_container(self, container):
+    def delete_container(self, container, response_dict=None):
         """Wrapper for :func:`delete_container`"""
-        return self._retry(None, delete_container, container)
+        return self._retry(None, delete_container, container,
+                           response_dict=response_dict)
 
     def head_object(self, container, obj):
         """Wrapper for :func:`head_object`"""
         return self._retry(None, head_object, container, obj)
 
     def get_object(self, container, obj, resp_chunk_size=None,
-                   query_string=None):
+                   query_string=None, response_dict=None):
         """Wrapper for :func:`get_object`"""
         return self._retry(None, get_object, container, obj,
                            resp_chunk_size=resp_chunk_size,
-                           query_string=query_string)
+                           query_string=query_string,
+                           response_dict=response_dict)
 
     def put_object(self, container, obj, contents, content_length=None,
                    etag=None, chunk_size=None, content_type=None,
-                   headers=None, query_string=None):
+                   headers=None, query_string=None, response_dict=None):
         """Wrapper for :func:`put_object`"""
 
         def _default_reset(*args, **kwargs):
@@ -1155,13 +1242,17 @@ class Connection(object):
         return self._retry(reset_func, put_object, container, obj, contents,
                            content_length=content_length, etag=etag,
                            chunk_size=chunk_size, content_type=content_type,
-                           headers=headers, query_string=query_string)
+                           headers=headers, query_string=query_string,
+                           response_dict=response_dict)
 
-    def post_object(self, container, obj, headers):
+    def post_object(self, container, obj, headers, response_dict=None):
         """Wrapper for :func:`post_object`"""
-        return self._retry(None, post_object, container, obj, headers)
+        return self._retry(None, post_object, container, obj, headers,
+                           response_dict=response_dict)
 
-    def delete_object(self, container, obj, query_string=None):
+    def delete_object(self, container, obj, query_string=None,
+                      response_dict=None):
         """Wrapper for :func:`delete_object`"""
         return self._retry(None, delete_object, container, obj,
-                           query_string=query_string)
+                           query_string=query_string,
+                           response_dict=response_dict)