diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for network-arbitrary
 
+## 0.3.0.0  -- 2018-01-06
+
+* Ensure URI shrink produces valid URIs
+
 ## 0.2.0.0  -- 2018-01-06
 
 * Add top-level module for importing everything
diff --git a/network-arbitrary.cabal b/network-arbitrary.cabal
--- a/network-arbitrary.cabal
+++ b/network-arbitrary.cabal
@@ -1,5 +1,5 @@
 name:                network-arbitrary
-version:             0.2.0.0
+version:             0.3.0.0
 synopsis:            Arbitrary Instances for Network Types
 
 description:         
diff --git a/src/Network/URI/Arbitrary.hs b/src/Network/URI/Arbitrary.hs
--- a/src/Network/URI/Arbitrary.hs
+++ b/src/Network/URI/Arbitrary.hs
@@ -15,7 +15,7 @@
 import Control.Applicative ((<$>), (<*>))
 import Control.Monad (replicateM)
 import Data.List (intercalate)
-import Network.URI (URI (..), URIAuth (..))
+import Network.URI (parseURIReference, URI (..), URIAuth (..), uriToString)
 import Test.QuickCheck (Arbitrary (arbitrary, shrink), choose, elements, Gen, listOf, listOf1, oneof, suchThat)
 
 instance Arbitrary URI where
@@ -29,7 +29,11 @@
        return URI {..}
     where emptyAuthority URIAuth{..} = all null [uriUserInfo, uriRegName, uriPort]
 
-  shrink URI{..} = [ URI uriScheme' uriAuthority' uriPath' uriQuery' uriFragment' | (uriScheme', uriAuthority', uriPath', uriQuery', uriFragment') <- shrink (uriScheme, uriAuthority, uriPath, uriQuery, uriFragment) ]
+  shrink URI{..} = filter isURI [ URI uriScheme' uriAuthority' uriPath' uriQuery' uriFragment' | (uriScheme', uriAuthority', uriPath', uriQuery', uriFragment') <- shrink (uriScheme, uriAuthority, uriPath, uriQuery, uriFragment) ]
+    where isURI u = case parseURIReference (uriToString id u "") of
+                      Just u' -> u' == u
+                      Nothing -> False
+
 
 instance Arbitrary URIAuth where
   arbitrary = URIAuth <$> userinfo
