diff --git a/docs/as-module.rst b/docs/as-module.rst
index 79c545c..5dcac44 100644
--- a/docs/as-module.rst
+++ b/docs/as-module.rst
@@ -198,6 +198,8 @@ Exceptions
 
 .. autoexception:: BadCredentialsException
 
+.. autoexception:: PostChangedException
+
 .. autoexception:: TooManyRequestsException
 
 ``InstaloaderContext`` (Low-level functions)
diff --git a/instaloader/exceptions.py b/instaloader/exceptions.py
index 5041f3a..0fc7196 100644
--- a/instaloader/exceptions.py
+++ b/instaloader/exceptions.py
@@ -57,5 +57,10 @@ class ConnectionException(InstaloaderException):
     pass
 
 
+class PostChangedException(InstaloaderException):
+    """.. versionadded:: 4.2.2"""
+    pass
+
+
 class TooManyRequestsException(ConnectionException):
     pass
diff --git a/instaloader/instaloader.py b/instaloader/instaloader.py
index 5c4c65e..15248f0 100644
--- a/instaloader/instaloader.py
+++ b/instaloader/instaloader.py
@@ -939,8 +939,22 @@ class Instaloader:
                             self.context.log('<skipped>')
                             continue
                         with self.context.error_catcher("Download {} of {}".format(post, profile_name)):
-                            downloaded = self.download_post(post, target=profile_name)
-                            if fast_update and not downloaded:
+                            # The PostChangedException gets raised if the Post's id/shortcode changed while obtaining
+                            # additional metadata. This is most likely the case if a HTTP redirect takes place while
+                            # resolving the shortcode URL.
+                            # The `post_changed` variable keeps the fast-update functionality alive: A Post which is
+                            # obained after a redirect has probably already been downloaded as a previous Post of the
+                            # same Profile.
+                            # Observed in issue #225: https://github.com/instaloader/instaloader/issues/225
+                            post_changed = False
+                            while True:
+                                try:
+                                    downloaded = self.download_post(post, target=profile_name)
+                                    break
+                                except PostChangedException:
+                                    post_changed = True
+                                    continue
+                            if fast_update and not downloaded and not post_changed:
                                 break
 
         if stories and profiles:
diff --git a/instaloader/structures.py b/instaloader/structures.py
index 22f0465..4a7d0b2 100644
--- a/instaloader/structures.py
+++ b/instaloader/structures.py
@@ -128,6 +128,9 @@ class Post:
             pic_json = self._context.get_json("p/{0}/".format(self.shortcode), params={})
             self._full_metadata_dict = pic_json['entry_data']['PostPage'][0]['graphql']['shortcode_media']
             self._rhx_gis_str = pic_json['rhx_gis']
+            if self.mediaid != self._full_metadata_dict['id']:
+                self._node.update(self._full_metadata_dict)
+                raise PostChangedException
 
     @property
     def _full_metadata(self) -> Dict[str, Any]: