diff --git a/CHANGELOG b/CHANGELOG
index 50cae06e..cd4fa139 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,5 @@
 == Unreleased
+- Remove remaining Python2 compability code and usage of the "six" library ([#753](https://github.com/Shopify/shopify_python_api/pull/753))
 
 == Version 12.7.0
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a08624f8..490f988b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,6 +5,4 @@ Please open an issue here if you encounter a specific bug with this API client l
 
 General questions about the Shopify API and usage of this package (not necessarily a bug) should be posted on the [Shopify forums](https://ecommerce.shopify.com/c/shopify-apis-and-technology).
 
-For compatibility across Python 2 and Python 3, look into [Six](https://six.readthedocs.io/).
-
 When in doubt, post on the forum first. You'll likely have your questions answered more quickly if you post there; more people monitor the forum than Github.
diff --git a/pylintrc b/pylintrc
index 97de81bf..1b7f811b 100644
--- a/pylintrc
+++ b/pylintrc
@@ -335,7 +335,7 @@ callbacks=cb_,_cb
 
 # List of qualified module names which can have objects that can redefine
 # builtins.
-redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
+redefining-builtins-modules=future.builtins,functools
 
 
 [LOGGING]
diff --git a/scripts/shopify_api.py b/scripts/shopify_api.py
index 5dfab93a..13a48e3d 100755
--- a/scripts/shopify_api.py
+++ b/scripts/shopify_api.py
@@ -9,8 +9,6 @@
 import subprocess
 import functools
 import yaml
-import six
-from six.moves import input, map
 
 
 def start_interpreter(**variables):
@@ -106,8 +104,7 @@ def help(cls, task=None):
             print(task_func.__doc__)
 
 
-@six.add_metaclass(TasksMeta)
-class Tasks(object):
+class Tasks(metaclass=TasksMeta):
     _shop_config_dir = os.path.join(os.environ["HOME"], ".shopify", "shops")
     _default_symlink = os.path.join(_shop_config_dir, "default")
     _default_api_version = "unstable"
diff --git a/setup.py b/setup.py
index eb23ab08..9a0ea5f3 100755
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,6 @@
         "PyJWT >= 2.0.0",
         "PyYAML>=6.0.1; python_version>='3.12'",
         "PyYAML; python_version<'3.12'",
-        "six",
     ],
     test_suite="test",
     tests_require=[
diff --git a/shopify/api_access.py b/shopify/api_access.py
index d5ffbe35..7842b431 100644
--- a/shopify/api_access.py
+++ b/shopify/api_access.py
@@ -2,13 +2,6 @@
 import sys
 
 
-def basestring_type():
-    if sys.version_info[0] < 3:  # Backwards compatibility for python < v3.0.0
-        return basestring
-    else:
-        return str
-
-
 class ApiAccessError(Exception):
     pass
 
@@ -20,7 +13,7 @@ class ApiAccess:
     IMPLIED_SCOPE_RE = re.compile(r"\A(?P<unauthenticated>unauthenticated_)?write_(?P<resource>.*)\Z")
 
     def __init__(self, scopes):
-        if isinstance(scopes, basestring_type()):
+        if isinstance(scopes, str):
             scopes = scopes.split(self.SCOPE_DELIMITER)
 
         self.__store_scopes(scopes)
diff --git a/shopify/api_version.py b/shopify/api_version.py
index 32276668..8f8eaa96 100644
--- a/shopify/api_version.py
+++ b/shopify/api_version.py
@@ -9,7 +9,7 @@ class VersionNotFoundError(Exception):
     pass
 
 
-class ApiVersion(object):
+class ApiVersion:
     versions = {}
 
     @classmethod
diff --git a/shopify/base.py b/shopify/base.py
index 449e288b..f6f03c24 100644
--- a/shopify/base.py
+++ b/shopify/base.py
@@ -5,8 +5,7 @@
 import shopify
 import threading
 import sys
-from six.moves import urllib
-import six
+import urllib.parse
 
 from shopify.collection import PaginatedCollection
 from pyactiveresource.collection import Collection
@@ -152,8 +151,7 @@ def set_url(cls, value):
     url = property(get_url, set_url, None, "Base URL including protocol and shopify domain")
 
 
-@six.add_metaclass(ShopifyResourceMeta)
-class ShopifyResource(ActiveResource, mixins.Countable):
+class ShopifyResource(ActiveResource, mixins.Countable, metaclass=ShopifyResourceMeta):
     _format = formats.JSONFormat
     _threadlocal = threading.local()
     _headers = {"User-Agent": "ShopifyPythonAPI/%s Python/%s" % (shopify.VERSION, sys.version.split(" ", 1)[0])}
diff --git a/shopify/collection.py b/shopify/collection.py
index 62728eb9..a8397dfe 100644
--- a/shopify/collection.py
+++ b/shopify/collection.py
@@ -125,7 +125,7 @@ def __len__(self):
         return count + super(PaginatedCollection, self).__len__()
 
 
-class PaginatedIterator(object):
+class PaginatedIterator:
     """
     This class implements an iterator over paginated collections which aims to
     be more memory-efficient by not keeping more than one page in memory at a
diff --git a/shopify/limits.py b/shopify/limits.py
index 0246c793..29652f09 100644
--- a/shopify/limits.py
+++ b/shopify/limits.py
@@ -1,7 +1,7 @@
 import shopify
 
 
-class Limits(object):
+class Limits:
     """
     API Calls Limit
     https://help.shopify.com/en/api/getting-started/api-call-limit
diff --git a/shopify/mixins.py b/shopify/mixins.py
index 54496dbf..366fa146 100644
--- a/shopify/mixins.py
+++ b/shopify/mixins.py
@@ -1,7 +1,7 @@
 import shopify.resources
 
 
-class Countable(object):
+class Countable:
     @classmethod
     def count(cls, _options=None, **kwargs):
         if _options is None:
@@ -9,7 +9,7 @@ def count(cls, _options=None, **kwargs):
         return int(cls.get("count", **_options))
 
 
-class Metafields(object):
+class Metafields:
     def metafields(self, _options=None, **kwargs):
         if _options is None:
             _options = kwargs
@@ -29,6 +29,6 @@ def add_metafield(self, metafield):
         return metafield
 
 
-class Events(object):
+class Events:
     def events(self):
         return shopify.resources.Event.find(resource=self.__class__.plural, resource_id=self.id)
diff --git a/shopify/resources/graphql.py b/shopify/resources/graphql.py
index 33525ef1..00807b15 100644
--- a/shopify/resources/graphql.py
+++ b/shopify/resources/graphql.py
@@ -1,7 +1,9 @@
+import json
+import urllib.error
+import urllib.request
+
 import shopify
 from ..base import ShopifyResource
-from six.moves import urllib
-import json
 
 
 class GraphQL:
diff --git a/shopify/resources/image.py b/shopify/resources/image.py
index 1a4d13fb..e6626028 100644
--- a/shopify/resources/image.py
+++ b/shopify/resources/image.py
@@ -1,6 +1,6 @@
 from ..base import ShopifyResource
 from ..resources import Metafield
-from six.moves import urllib
+import urllib.parse
 import base64
 import re
 
diff --git a/shopify/session.py b/shopify/session.py
index 39ce5f7b..62e852d6 100644
--- a/shopify/session.py
+++ b/shopify/session.py
@@ -1,6 +1,8 @@
 import time
 import hmac
 import json
+import urllib.parse
+import urllib.request
 from hashlib import sha256
 
 try:
@@ -9,17 +11,15 @@
     import json
 import re
 from contextlib import contextmanager
-from six.moves import urllib
 from shopify.api_access import ApiAccess
 from shopify.api_version import ApiVersion, Release, Unstable
-import six
 
 
 class ValidationException(Exception):
     pass
 
 
-class Session(object):
+class Session:
     api_key = None
     secret = None
     protocol = "https"
@@ -28,7 +28,7 @@ class Session(object):
 
     @classmethod
     def setup(cls, **kwargs):
-        for k, v in six.iteritems(kwargs):
+        for k, v in kwargs.items():
             setattr(cls, k, v)
 
     @classmethod
@@ -165,7 +165,7 @@ def __encoded_params_for_signature(cls, params):
         """
 
         def encoded_pairs(params):
-            for k, v in six.iteritems(params):
+            for k, v in params.items():
                 if k == "hmac":
                     continue
 
diff --git a/shopify/session_token.py b/shopify/session_token.py
index 91a4970b..09b77b0a 100644
--- a/shopify/session_token.py
+++ b/shopify/session_token.py
@@ -1,16 +1,10 @@
 import jwt
 import re
-import six
 import sys
+from urllib.parse import urljoin
 
 from shopify.utils import shop_url
 
-if sys.version_info[0] < 3:  # Backwards compatibility for python < v3.0.0
-    from urlparse import urljoin
-else:
-    from urllib.parse import urljoin
-
-
 ALGORITHM = "HS256"
 PREFIX = "Bearer "
 REQUIRED_FIELDS = ["iss", "dest", "sub", "jti", "sid"]
@@ -61,7 +55,7 @@ def _decode_session_token(session_token, api_key, secret):
             options={"require": REQUIRED_FIELDS},
         )
     except jwt.exceptions.PyJWTError as exception:
-        six.raise_from(SessionTokenError(str(exception)), exception)
+        raise SessionTokenError(str(exception)) from exception
 
 
 def _validate_issuer(decoded_payload):
diff --git a/shopify/utils/shop_url.py b/shopify/utils/shop_url.py
index 76e088a7..7a645046 100644
--- a/shopify/utils/shop_url.py
+++ b/shopify/utils/shop_url.py
@@ -1,10 +1,6 @@
 import re
 import sys
-
-if sys.version_info[0] < 3:  # Backwards compatibility for python < v3.0.0
-    from urlparse import urlparse
-else:
-    from urllib.parse import urlparse
+from urllib.parse import urlparse
 
 HOSTNAME_PATTERN = r"[a-z0-9][a-z0-9-]*[a-z0-9]"
 
diff --git a/test/inventory_level_test.py b/test/inventory_level_test.py
index cf621b7c..37cebffa 100644
--- a/test/inventory_level_test.py
+++ b/test/inventory_level_test.py
@@ -1,6 +1,6 @@
 import shopify
 import json
-from six.moves.urllib.parse import urlencode
+from urllib.parse import urlencode
 from test.test_helper import TestCase
 
 
diff --git a/test/session_test.py b/test/session_test.py
index d7cd5c3d..0265ff1c 100644
--- a/test/session_test.py
+++ b/test/session_test.py
@@ -3,8 +3,7 @@
 import hmac
 from hashlib import sha256
 import time
-from six.moves import urllib
-from six import u
+import urllib.parse
 
 
 class SessionTest(TestCase):
@@ -182,7 +181,7 @@ def test_hmac_validation(self):
             "shop": "some-shop.myshopify.com",
             "code": "a94a110d86d2452eb3e2af4cfb8a3828",
             "timestamp": "1337178173",
-            "hmac": u("2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2"),
+            "hmac": "2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2",
         }
         self.assertTrue(shopify.Session.validate_hmac(params))
 
@@ -192,7 +191,7 @@ def test_parameter_validation_handles_missing_params(self):
         params = {
             "shop": "some-shop.myshopify.com",
             "code": "a94a110d86d2452eb3e2af4cfb8a3828",
-            "hmac": u("2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2"),
+            "hmac": "2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2",
         }
         self.assertFalse(shopify.Session.validate_params(params))
 
@@ -204,7 +203,7 @@ def test_param_validation_of_param_values_with_lists(self):
                 2,
                 1,
             ],
-            "hmac": u("b93b9f82996f6f8bf9f1b7bbddec284c8fabacdc4e12dc80550b4705f3003b1e"),
+            "hmac": "b93b9f82996f6f8bf9f1b7bbddec284c8fabacdc4e12dc80550b4705f3003b1e",
         }
         self.assertEqual(True, shopify.Session.validate_hmac(params))
 
diff --git a/test/session_token_test.py b/test/session_token_test.py
index 0df7147f..45a9aedf 100644
--- a/test/session_token_test.py
+++ b/test/session_token_test.py
@@ -3,14 +3,10 @@
 from datetime import datetime, timedelta
 
 import jwt
-import sys
-
-if sys.version_info[0] < 3:  # Backwards compatibility for python < v3.0.0
-    import time
 
 
 def timestamp(date):
-    return time.mktime(date.timetuple()) if sys.version_info[0] < 3 else date.timestamp()
+    return date.timestamp()
 
 
 class TestSessionTokenGetDecodedSessionToken(TestCase):