diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2326ba02..09b79281 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+<a name="7.1.0"></a>
+# [7.1.0](https://github.com/multiformats/js-multiaddr/compare/v7.0.0...v7.1.0) (2019-09-10)
+
+
+### Features
+
+* add decapsulateCode method ([#98](https://github.com/multiformats/js-multiaddr/issues/98)) ([19a3940](https://github.com/multiformats/js-multiaddr/commit/19a3940))
+
+
+
 <a name="7.0.0"></a>
 # [7.0.0](https://github.com/multiformats/js-multiaddr/compare/v6.1.0...v7.0.0) (2019-09-03)
 
diff --git a/package.json b/package.json
index 00b509cf..accda8de 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "multiaddr",
-  "version": "7.0.0",
+  "version": "7.1.0",
   "description": "multiaddr implementation (binary + string representation of network addresses)",
   "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
   "main": "src/index.js",
diff --git a/src/index.js b/src/index.js
index 638e6b80..395cc576 100644
--- a/src/index.js
+++ b/src/index.js
@@ -237,6 +237,34 @@ Multiaddr.prototype.decapsulate = function decapsulate (addr) {
   return Multiaddr(s.slice(0, i))
 }
 
+/**
+ * A more reliable version of `decapsulate` if you are targeting a
+ * specific code, such as 421 (the `p2p` protocol code). The last index of the code
+ * will be removed from the `Multiaddr`, and a new instance will be returned.
+ * If the code is not present, the original `Multiaddr` is returned.
+ *
+ * @param {Number} code The code of the protocol to decapsulate from this Multiaddr
+ * @return {Multiaddr}
+ * @example
+ * const addr = Multiaddr('/ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC')
+ * // <Multiaddr 0400... - /ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC>
+ *
+ * addr.decapsulateCode(421).toString()
+ * // '/ip4/0.0.0.0/tcp/8080'
+ *
+ * Multiaddr('/ip4/127.0.0.1/tcp/8080').decapsulateCode(421).toString()
+ * // '/ip4/127.0.0.1/tcp/8080'
+ */
+Multiaddr.prototype.decapsulateCode = function decapsulateCode (code) {
+  const tuples = this.tuples()
+  for (let i = tuples.length - 1; i >= 0; i--) {
+    if (tuples[i][0] === code) {
+      return Multiaddr(codec.tuplesToBuffer(tuples.slice(0, i)))
+    }
+  }
+  return this
+}
+
 /**
  * Extract the peerId if the multiaddr contains one
  *
diff --git a/test/index.spec.js b/test/index.spec.js
index ed37bf62..d6e4f0fb 100644
--- a/test/index.spec.js
+++ b/test/index.spec.js
@@ -598,6 +598,22 @@ describe('helpers', () => {
     })
   })
 
+  describe('.decapsulateCode', () => {
+    it('removes the last occurrence of the code from the multiaddr', () => {
+      const relayTCP = multiaddr('/ip4/0.0.0.0/tcp/8080')
+      const relay = relayTCP.encapsulate('/p2p/QmZR5a9AAXGqQF2ADqoDdGS8zvqv8n3Pag6TDDnTNMcFW6/p2p-circuit')
+      const target = multiaddr('/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC')
+      const original = relay.encapsulate(target)
+      expect(original.decapsulateCode(421)).to.eql(relay)
+      expect(relay.decapsulateCode(421)).to.eql(relayTCP)
+    })
+
+    it('ignores missing codes', () => {
+      const tcp = multiaddr('/ip4/0.0.0.0/tcp/8080')
+      expect(tcp.decapsulateCode(421)).to.eql(tcp)
+    })
+  })
+
   describe('.equals', () => {
     it('returns true for equal addresses', () => {
       const addr1 = multiaddr('/ip4/192.168.0.1')