diff --git a/README.md b/README.md
index 06f521f..8a6d9c5 100644
--- a/README.md
+++ b/README.md
@@ -35,40 +35,63 @@
 > npm i libp2p-websockets
 ```
 
-### Example
+### Constructor properties
 
 ```js
 const WS = require('libp2p-websockets')
-const multiaddr = require('multiaddr')
-const pipe = require('it-pipe')
-const { collect } = require('streaming-iterables')
 
-const addr = multiaddr('/ip4/0.0.0.0/tcp/9090/ws')
+const properties = {
+  upgrader,
+  filter
+}
 
-const ws = new WS({ upgrader })
-
-const listener = ws.createListener((socket) => {
-  console.log('new connection opened')
-  pipe(
-    ['hello'],
-    socket
-  )
-})
-
-await listener.listen(addr)
-console.log('listening')
-
-const socket = await ws.dial(addr)
-const values = await pipe(
-  socket,
-  collect
-)
-console.log(`Value: ${values.toString()}`)
-
-// Close connection after reading
-await listener.close()
+const ws = new WS(properties)
 ```
 
+| Name | Type | Description | Default |
+|------|------|-------------|---------|
+| upgrader | [`Upgrader`](https://github.com/libp2p/interface-transport#upgrader) | connection upgrader object with `upgradeOutbound` and `upgradeInbound` | **REQUIRED** |
+| filter | `(multiaddrs: Array<Multiaddr>) => Array<Multiaddr>` | override transport addresses filter | **Browser:** DNS+WSS multiaddrs / **Node.js:** DNS+{WS, WSS} multiaddrs |
+
+You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js).
+
+The available filters are:
+
+- `filters.all`
+  - Returns all TCP and DNS based addresses, both with `ws` or `wss`.
+- `filters.dnsWss`
+  - Returns all DNS based addresses with `wss`.
+- `filters.dnsWsOrWss`
+  - Returns all DNS based addresses, both with `ws` or `wss`.
+
+## Libp2p Usage Example
+
+```js
+const Libp2p = require('libp2p')
+const Websockets = require('libp2p-websockets')
+const filters = require('libp2p-websockets/src/filters')
+const MPLEX = require('libp2p-mplex')
+const { NOISE } = require('libp2p-noise')
+
+const transportKey = Websockets.prototype[Symbol.toStringTag]
+const node = await Libp2p.create({
+  modules: {
+    transport: [Websockets],
+    streamMuxer: [MPLEX],
+    connEncryption: [NOISE]
+  },
+  config: {
+    transport: {
+      [transportKey]: { // Transport properties -- Libp2p upgrader is automatically added
+        filter: filters.dnsWsOrWss
+      }
+    }
+  }
+})
+```
+
+For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports).
+
 ## API
 
 ### Transport
diff --git a/package.json b/package.json
index 2b38e64..fd9d78c 100644
--- a/package.json
+++ b/package.json
@@ -40,22 +40,24 @@
   "dependencies": {
     "abortable-iterator": "^3.0.0",
     "class-is": "^1.1.0",
-    "debug": "^4.1.1",
-    "err-code": "^2.0.0",
-    "it-ws": "^3.0.0",
-    "libp2p-utils": "^0.2.0",
-    "mafmt": "^8.0.0",
-    "multiaddr": "^8.0.0",
+    "debug": "^4.2.0",
+    "err-code": "^2.0.3",
+    "ipfs-utils": "^4.0.1",
+    "it-ws": "^3.0.2",
+    "libp2p-utils": "^0.2.1",
+    "mafmt": "^8.0.1",
+    "multiaddr": "^8.1.1",
     "multiaddr-to-uri": "^6.0.0",
     "p-timeout": "^3.2.0"
   },
   "devDependencies": {
     "abort-controller": "^3.0.0",
-    "aegir": "^25.0.0",
+    "aegir": "^28.1.0",
     "bl": "^4.0.0",
+    "is-loopback-addr": "^1.0.1",
     "it-goodbye": "^2.0.1",
     "it-pipe": "^1.0.1",
-    "libp2p-interfaces": "^0.4.0",
+    "libp2p-interfaces": "^0.7.1",
     "streaming-iterables": "^5.0.2",
     "uint8arrays": "^1.1.0"
   },
diff --git a/src/constants.js b/src/constants.js
index b7ab8fe..28f2634 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -4,5 +4,9 @@
 exports.CODE_P2P = 421
 exports.CODE_CIRCUIT = 290
 
+exports.CODE_TCP = 6
+exports.CODE_WS = 477
+exports.CODE_WSS = 478
+
 // Time to wait for a connection to close gracefully before destroying it manually
 exports.CLOSE_TIMEOUT = 2000
diff --git a/src/filters.js b/src/filters.js
new file mode 100644
index 0000000..2aa0bc8
--- /dev/null
+++ b/src/filters.js
@@ -0,0 +1,49 @@
+'use strict'
+
+const mafmt = require('mafmt')
+const {
+  CODE_CIRCUIT,
+  CODE_P2P,
+  CODE_TCP,
+  CODE_WS,
+  CODE_WSS
+} = require('./constants')
+
+module.exports = {
+  all: (multiaddrs) => multiaddrs.filter((ma) => {
+    if (ma.protoCodes().includes(CODE_CIRCUIT)) {
+      return false
+    }
+
+    const testMa = ma.decapsulateCode(CODE_P2P)
+
+    return mafmt.WebSockets.matches(testMa) ||
+      mafmt.WebSocketsSecure.matches(testMa)
+  }),
+  dnsWss: (multiaddrs) => multiaddrs.filter((ma) => {
+    if (ma.protoCodes().includes(CODE_CIRCUIT)) {
+      return false
+    }
+
+    const testMa = ma.decapsulateCode(CODE_P2P)
+
+    return mafmt.WebSocketsSecure.matches(testMa) &&
+      mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WSS))
+  }),
+  dnsWsOrWss: (multiaddrs) => multiaddrs.filter((ma) => {
+    if (ma.protoCodes().includes(CODE_CIRCUIT)) {
+      return false
+    }
+
+    const testMa = ma.decapsulateCode(CODE_P2P)
+
+    // WS
+    if (mafmt.WebSockets.matches(testMa)) {
+      return mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WS))
+    }
+
+    // WSS
+    return mafmt.WebSocketsSecure.matches(testMa) &&
+      mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WSS))
+  })
+}
diff --git a/src/index.js b/src/index.js
index d22bdca..3d985ae 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,38 +1,40 @@
 'use strict'
 
 const connect = require('it-ws/client')
-const mafmt = require('mafmt')
 const withIs = require('class-is')
 const toUri = require('multiaddr-to-uri')
 const { AbortError } = require('abortable-iterator')
 
 const log = require('debug')('libp2p:websockets')
+const env = require('ipfs-utils/src/env')
 
 const createListener = require('./listener')
 const toConnection = require('./socket-to-conn')
-const { CODE_CIRCUIT, CODE_P2P } = require('./constants')
+const filters = require('./filters')
 
 /**
  * @class WebSockets
  */
 class WebSockets {
   /**
-   * @constructor
+   * @class
    * @param {object} options
    * @param {Upgrader} options.upgrader
+   * @param {(multiaddrs: Array<Multiaddr>) => Array<Multiaddr>} options.filter - override transport addresses filter
    */
-  constructor ({ upgrader }) {
+  constructor ({ upgrader, filter }) {
     if (!upgrader) {
       throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.')
     }
     this._upgrader = upgrader
+    this._filter = filter
   }
 
   /**
    * @async
    * @param {Multiaddr} ma
    * @param {object} [options]
-   * @param {AbortSignal} [options.signal] Used to abort dial requests
+   * @param {AbortSignal} [options.signal] - Used to abort dial requests
    * @returns {Connection} An upgraded Connection
    */
   async dial (ma, options = {}) {
@@ -51,7 +53,7 @@ class WebSockets {
    * @private
    * @param {Multiaddr} ma
    * @param {object} [options]
-   * @param {AbortSignal} [options.signal] Used to abort dial requests
+   * @param {AbortSignal} [options.signal] - Used to abort dial requests
    * @returns {Promise<WebSocket>} Resolves a extended duplex iterable on top of a WebSocket
    */
   async _connect (ma, options = {}) {
@@ -97,8 +99,9 @@ class WebSockets {
    * Creates a Websockets listener. The provided `handler` function will be called
    * anytime a new incoming Connection has been successfully upgraded via
    * `upgrader.upgradeInbound`.
+   *
    * @param {object} [options]
-   * @param {http.Server} [options.server] A pre-created Node.js HTTP/S server.
+   * @param {http.Server} [options.server] - A pre-created Node.js HTTP/S server.
    * @param {function (Connection)} handler
    * @returns {Listener} A Websockets listener
    */
@@ -112,21 +115,26 @@ class WebSockets {
   }
 
   /**
-   * Takes a list of `Multiaddr`s and returns only valid Websockets addresses
+   * Takes a list of `Multiaddr`s and returns only valid Websockets addresses.
+   * By default, in a browser environment only DNS+WSS multiaddr is accepted,
+   * while in a Node.js environment DNS+{WS, WSS} multiaddrs are accepted.
+   *
    * @param {Multiaddr[]} multiaddrs
    * @returns {Multiaddr[]} Valid Websockets multiaddrs
    */
   filter (multiaddrs) {
     multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
 
-    return multiaddrs.filter((ma) => {
-      if (ma.protoCodes().includes(CODE_CIRCUIT)) {
-        return false
-      }
+    if (this._filter) {
+      return this._filter(multiaddrs)
+    }
 
-      return mafmt.WebSockets.matches(ma.decapsulateCode(CODE_P2P)) ||
-        mafmt.WebSocketsSecure.matches(ma.decapsulateCode(CODE_P2P))
-    })
+    // Browser
+    if (env.isBrowser || env.isWebWorker) {
+      return filters.dnsWss(multiaddrs)
+    }
+
+    return filters.all(multiaddrs)
   }
 }
 
diff --git a/test/browser.js b/test/browser.js
index 261bbea..092646e 100644
--- a/test/browser.js
+++ b/test/browser.js
@@ -34,6 +34,16 @@ describe('libp2p-websockets', () => {
     expect(results).to.eql([message])
   })
 
+  it('should filter out no DNS websocket addresses', function () {
+    const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws')
+    const ma2 = multiaddr('/ip4/127.0.0.1/tcp/443/wss')
+    const ma3 = multiaddr('/ip6/::1/tcp/80/ws')
+    const ma4 = multiaddr('/ip6/::1/tcp/443/wss')
+
+    const valid = ws.filter([ma1, ma2, ma3, ma4])
+    expect(valid.length).to.equal(0)
+  })
+
   describe('stress', () => {
     it('one big write', async () => {
       const rawMessage = new Uint8Array(1000000).fill('a')
diff --git a/test/compliance.node.js b/test/compliance.node.js
index 43e83e9..ece8c7f 100644
--- a/test/compliance.node.js
+++ b/test/compliance.node.js
@@ -5,11 +5,12 @@ const tests = require('libp2p-interfaces/src/transport/tests')
 const multiaddr = require('multiaddr')
 const http = require('http')
 const WS = require('../src')
+const filters = require('../src/filters')
 
 describe('interface-transport compliance', () => {
   tests({
     async setup ({ upgrader }) { // eslint-disable-line require-await
-      const ws = new WS({ upgrader })
+      const ws = new WS({ upgrader, filter: filters.all })
       const addrs = [
         multiaddr('/ip4/127.0.0.1/tcp/9091/ws'),
         multiaddr('/ip4/127.0.0.1/tcp/9092/ws'),
diff --git a/test/node.js b/test/node.js
index ad51a99..83bcd8f 100644
--- a/test/node.js
+++ b/test/node.js
@@ -8,12 +8,14 @@ const fs = require('fs')
 const { expect } = require('aegir/utils/chai')
 const multiaddr = require('multiaddr')
 const goodbye = require('it-goodbye')
+const isLoopbackAddr = require('is-loopback-addr')
 const { collect } = require('streaming-iterables')
 const pipe = require('it-pipe')
 const BufferList = require('bl/BufferList')
 const uint8ArrayFromString = require('uint8arrays/from-string')
 
 const WS = require('../src')
+const filters = require('../src/filters')
 
 require('./compliance.node')
 
@@ -250,6 +252,36 @@ describe('dial', () => {
     })
   })
 
+  describe('ip4 no loopback', () => {
+    let ws
+    let listener
+    const ma = multiaddr('/ip4/0.0.0.0/tcp/0/ws')
+
+    beforeEach(() => {
+      ws = new WS({ upgrader: mockUpgrader })
+      listener = ws.createListener(conn => pipe(conn, conn))
+      return listener.listen(ma)
+    })
+
+    afterEach(() => listener.close())
+
+    it('dial', async () => {
+      const addrs = listener.getAddrs().filter((ma) => {
+        const { address } = ma.nodeAddress()
+
+        return !isLoopbackAddr(address)
+      })
+
+      // Dial first no loopback address
+      const conn = await ws.dial(addrs[0])
+      const s = goodbye({ source: ['hey'], sink: collect })
+
+      const result = await pipe(s, conn, s)
+
+      expect(result).to.be.eql([uint8ArrayFromString('hey')])
+    })
+  })
+
   describe('ip4 with wss', () => {
     let ws
     let listener
@@ -327,11 +359,79 @@ describe('dial', () => {
 describe('filter addrs', () => {
   let ws
 
-  before(() => {
-    ws = new WS({ upgrader: mockUpgrader })
+  describe('default filter addrs with only dns', () => {
+    before(() => {
+      ws = new WS({ upgrader: mockUpgrader })
+    })
+
+    it('should filter out invalid WS addresses', function () {
+      const ma1 = multiaddr('/ip4/127.0.0.1/tcp/9090')
+      const ma2 = multiaddr('/ip4/127.0.0.1/udp/9090')
+      const ma3 = multiaddr('/ip6/::1/tcp/80')
+      const ma4 = multiaddr('/dnsaddr/ipfs.io/tcp/80')
+
+      const valid = ws.filter([ma1, ma2, ma3, ma4])
+      expect(valid.length).to.equal(0)
+    })
+
+    it('should filter correct dns address', function () {
+      const ma1 = multiaddr('/dnsaddr/ipfs.io/ws')
+      const ma2 = multiaddr('/dnsaddr/ipfs.io/tcp/80/ws')
+      const ma3 = multiaddr('/dnsaddr/ipfs.io/tcp/80/wss')
+
+      const valid = ws.filter([ma1, ma2, ma3])
+      expect(valid.length).to.equal(3)
+      expect(valid[0]).to.deep.equal(ma1)
+      expect(valid[1]).to.deep.equal(ma2)
+      expect(valid[2]).to.deep.equal(ma3)
+    })
+
+    it('should filter correct dns address with ipfs id', function () {
+      const ma1 = multiaddr('/dnsaddr/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
+      const ma2 = multiaddr('/dnsaddr/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
+
+      const valid = ws.filter([ma1, ma2])
+      expect(valid.length).to.equal(2)
+      expect(valid[0]).to.deep.equal(ma1)
+      expect(valid[1]).to.deep.equal(ma2)
+    })
+
+    it('should filter correct dns4 address', function () {
+      const ma1 = multiaddr('/dns4/ipfs.io/tcp/80/ws')
+      const ma2 = multiaddr('/dns4/ipfs.io/tcp/443/wss')
+
+      const valid = ws.filter([ma1, ma2])
+      expect(valid.length).to.equal(2)
+      expect(valid[0]).to.deep.equal(ma1)
+      expect(valid[1]).to.deep.equal(ma2)
+    })
+
+    it('should filter correct dns6 address', function () {
+      const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws')
+      const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss')
+
+      const valid = ws.filter([ma1, ma2])
+      expect(valid.length).to.equal(2)
+      expect(valid[0]).to.deep.equal(ma1)
+      expect(valid[1]).to.deep.equal(ma2)
+    })
+
+    it('should filter correct dns6 address with ipfs id', function () {
+      const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
+      const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
+
+      const valid = ws.filter([ma1, ma2])
+      expect(valid.length).to.equal(2)
+      expect(valid[0]).to.deep.equal(ma1)
+      expect(valid[1]).to.deep.equal(ma2)
+    })
   })
 
-  describe('filter valid addrs for this transport', function () {
+  describe('custom filter addrs', () => {
+    before(() => {
+      ws = new WS({ upgrader: mockUpgrader, filter: filters.all })
+    })
+
     it('should fail invalid WS addresses', function () {
       const ma1 = multiaddr('/ip4/127.0.0.1/tcp/9090')
       const ma2 = multiaddr('/ip4/127.0.0.1/udp/9090')
@@ -447,14 +547,13 @@ describe('filter addrs', () => {
       expect(valid[0]).to.deep.equal(ma1)
       expect(valid[1]).to.deep.equal(ma4)
     })
-  })
 
-  it('filter a single addr for this transport', (done) => {
-    const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
+    it('filter a single addr for this transport', () => {
+      const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
 
-    const valid = ws.filter(ma)
-    expect(valid.length).to.equal(1)
-    expect(valid[0]).to.deep.equal(ma)
-    done()
+      const valid = ws.filter(ma)
+      expect(valid.length).to.equal(1)
+      expect(valid[0]).to.deep.equal(ma)
+    })
   })
 })