Repository: streamlink/streamlink
Pull request #1918 (2018-07-10 09:56:59)

stream.hls_playlist: fix some regex pattern & code optimization
- declares explicit all pattern strings as raw strings
- move global & all other regex pattern to precompiled regex objects to `M3U8Parser`
- code optimization for parser loop


codecov[bot]: # [Codecov](https://codecov.io/gh/streamlink/streamlink/pull/1918?src=pr&el=h1) Report
> Merging [#1918](https://codecov.io/gh/streamlink/streamlink/pull/1918?src=pr&el=desc) into [master](https://codecov.io/gh/streamlink/streamlink/commit/fbdea863d6c7eb037a11f1f698ff23cb5afa6d47?src=pr&el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `86.66%`.


```diff
@@            Coverage Diff             @@
##           master    #1918      +/-   ##
==========================================
+ Coverage   51.33%   51.35%   +0.02%     
==========================================
  Files         241      241              
  Lines       14121    14127       +6     
==========================================
+ Hits         7249     7255       +6     
  Misses       6872     6872
```

beardypig: Why not use `iter` in place of `enumerate`?
beardypig: @Billy2011 does this version speed it up for you on the VU+ boxes? 
Billy2011: On the VU+ boxes I use the version with `cStringIO` - I have not tested this last version.
beardypig: OK, it would be good to know if this does speed it up at all - otherwise the commit messages won't be accurate :)

Patch:
diff --git a/src/streamlink/plugins/abweb.py b/src/streamlink/plugins/abweb.py
index 34005b1e..8447a594 100644
--- a/src/streamlink/plugins/abweb.py
+++ b/src/streamlink/plugins/abweb.py
@@ -5,7 +5,6 @@ from streamlink.cache import Cache
 from streamlink.exceptions import PluginError
 from streamlink.plugin import Plugin
 from streamlink.plugin import PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.utils import update_scheme
@@ -72,7 +71,7 @@ class ABweb(Plugin):
 
     def get_iframe_url(self):
         self.logger.debug('search for an iframe')
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self._iframe_re.search(res.text)
         if not m:
             raise PluginError('No iframe found.')
@@ -84,7 +83,7 @@ class ABweb(Plugin):
 
     def get_hls_url(self, iframe_url):
         self.logger.debug('search for hls url')
-        res = http.get(iframe_url)
+        res = self.session.http.get(iframe_url)
         m = self._hls_re.search(res.text)
         if not m:
             raise PluginError('No playlist found.')
@@ -95,7 +94,7 @@ class ABweb(Plugin):
         '''login and update cached cookies'''
         self.logger.debug('login ...')
 
-        res = http.get(self.login_url)
+        res = self.session.http.get(self.login_url)
         input_list = self._input_re.findall(res.text)
         if not input_list:
             raise PluginError('Missing input data on login website.')
@@ -122,9 +121,9 @@ class ABweb(Plugin):
         }
         data.update(login_data)
 
-        res = http.post(self.login_url, data=data)
+        res = self.session.http.post(self.login_url, data=data)
 
-        for cookie in http.cookies:
+        for cookie in self.session.http.cookies:
             self._session_attributes.set(cookie.name, cookie.value, expires=3600 * 24)
 
         if self._session_attributes.get('ASP.NET_SessionId') and self._session_attributes.get('.abportail1'):
@@ -136,7 +135,7 @@ class ABweb(Plugin):
             return False
 
     def _get_streams(self):
-        http.headers.update({'User-Agent': useragents.CHROME,
+        self.session.http.headers.update({'User-Agent': useragents.CHROME,
                              'Referer': 'http://www.abweb.com/BIS-TV-Online/bistvo-tele-universal.aspx'})
 
         login_username = self.get_option('username')
@@ -160,14 +159,14 @@ class ABweb(Plugin):
                 self._authed = False
             else:
                 self.logger.info('Attempting to authenticate using cached cookies')
-                http.cookies.set('ASP.NET_SessionId', self._session_attributes.get('ASP.NET_SessionId'))
-                http.cookies.set('.abportail1', self._session_attributes.get('.abportail1'))
+                self.session.http.cookies.set('ASP.NET_SessionId', self._session_attributes.get('ASP.NET_SessionId'))
+                self.session.http.cookies.set('.abportail1', self._session_attributes.get('.abportail1'))
 
         if not self._authed and not self._login(login_username, login_password):
             return
 
         iframe_url = self.get_iframe_url()
-        http.headers.update({'Referer': iframe_url})
+        self.session.http.headers.update({'Referer': iframe_url})
 
         hls_url = self.get_hls_url(iframe_url)
         hls_url = update_scheme(self.url, hls_url)
diff --git a/src/streamlink/plugins/adultswim.py b/src/streamlink/plugins/adultswim.py
index f90b5173..9eb0cbe2 100644
--- a/src/streamlink/plugins/adultswim.py
+++ b/src/streamlink/plugins/adultswim.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.plugin import Plugin
 from streamlink.plugin.api import StreamMapper
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api import useragents
 from streamlink.stream import HDSStream
 from streamlink.stream import HLSStream
@@ -58,7 +58,7 @@ class AdultSwim(Plugin):
 
     def _get_show_streams(self, stream_data, show, episode, platform="desktop"):
         video_id = parse_json(stream_data.group(1), schema=self.vod_id_schema)
-        res = http.get(self.vod_api, params={"platform": platform, "id": video_id})
+        res = self.session.http.get(self.vod_api, params={"platform": platform, "id": video_id})
 
         # create a unique list of the stream manifest URLs
         streams = []
@@ -103,8 +103,8 @@ class AdultSwim(Plugin):
         if stream_id:
             api_url = self.API_URL.format(id=stream_id)
 
-            res = http.get(api_url, headers={"User-Agent": useragents.SAFARI_8})
-            stream_data = http.json(res, schema=self._api_schema)
+            res = self.session.http.get(api_url, headers={"User-Agent": useragents.SAFARI_8})
+            stream_data = self.session.http.json(res, schema=self._api_schema)
 
             mapper = StreamMapper(lambda fmt, surl: surl.endswith(fmt))
             mapper.map(".m3u8", HLSStream.parse_variant_playlist, self.session)
@@ -124,7 +124,7 @@ class AdultSwim(Plugin):
         if live_stream:
             show_name = show_name or "live-stream"
 
-        res = http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
+        res = self.session.http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
         # find the big blob of stream info in the page
         stream_data = self._stream_data_re.search(res.text)
 
diff --git a/src/streamlink/plugins/afreeca.py b/src/streamlink/plugins/afreeca.py
index b345495c..23c76420 100644
--- a/src/streamlink/plugins/afreeca.py
+++ b/src/streamlink/plugins/afreeca.py
@@ -2,7 +2,6 @@ import re
 
 from streamlink.plugin import Plugin
 from streamlink.plugin import PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -83,8 +82,8 @@ class AfreecaTV(Plugin):
             "player_type": "html5"
         }
 
-        res = http.post(CHANNEL_API_URL, data=data)
-        return http.json(res, schema=_channel_schema)
+        res = self.session.http.post(CHANNEL_API_URL, data=data)
+        return self.session.http.json(res, schema=_channel_schema)
 
     def _get_hls_key(self, broadcast, username, quality):
         headers = {
@@ -98,16 +97,16 @@ class AfreecaTV(Plugin):
             "quality": quality,
             "type": "pwd"
         }
-        res = http.post(CHANNEL_API_URL, data=data, headers=headers)
-        return http.json(res, schema=_channel_schema)
+        res = self.session.http.post(CHANNEL_API_URL, data=data, headers=headers)
+        return self.session.http.json(res, schema=_channel_schema)
 
     def _get_stream_info(self, broadcast, quality, cdn, rmd):
         params = {
             "return_type": cdn,
             "broad_key": "{broadcast}-flash-{quality}-hls".format(**locals())
         }
-        res = http.get(STREAM_INFO_URLS.format(rmd=rmd), params=params)
-        return http.json(res, schema=_stream_schema)
+        res = self.session.http.get(STREAM_INFO_URLS.format(rmd=rmd), params=params)
+        return self.session.http.json(res, schema=_stream_schema)
 
     def _get_hls_stream(self, broadcast, username, quality, cdn, rmd):
         keyjson = self._get_hls_key(broadcast, username, quality)
@@ -132,8 +131,8 @@ class AfreecaTV(Plugin):
             "isSaveJoin": "false"
         }
 
-        res = http.post(self.login_url, data=data)
-        res = http.json(res)
+        res = self.session.http.post(self.login_url, data=data)
+        res = self.session.http.json(res)
         if res["RESULT"] == 1:
             return True
         else:
diff --git a/src/streamlink/plugins/aftonbladet.py b/src/streamlink/plugins/aftonbladet.py
index 91c38687..920d09ac 100644
--- a/src/streamlink/plugins/aftonbladet.py
+++ b/src/streamlink/plugins/aftonbladet.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream
 
 PLAYLIST_URL_FORMAT = "http://{address}/{path}/{filename}"
@@ -50,10 +50,10 @@ class Aftonbladet(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _embed_re.search(res.text)
         if match:
-            res = http.get(match.group(1))
+            res = self.session.http.get(match.group(1))
 
         match = _aptoma_id_re.search(res.text)
         if not match:
@@ -61,14 +61,14 @@ class Aftonbladet(Plugin):
 
         aptoma_id = match.group(1)
         if not _live_re.search(res.text):
-            res = http.get(METADATA_URL.format(aptoma_id))
-            metadata = http.json(res)
+            res = self.session.http.get(METADATA_URL.format(aptoma_id))
+            metadata = self.session.http.json(res)
             video_id = metadata["videoId"]
         else:
             video_id = aptoma_id
 
-        res = http.get(VIDEO_INFO_URL, params=dict(id=video_id))
-        video = http.json(res, schema=_video_schema)
+        res = self.session.http.get(VIDEO_INFO_URL, params=dict(id=video_id))
+        video = self.session.http.json(res, schema=_video_schema)
         streams = {}
         for fmt, providers in video["formats"].items():
             for name, provider in providers.items():
diff --git a/src/streamlink/plugins/aliez.py b/src/streamlink/plugins/aliez.py
index 9313ef5c..e7c00954 100644
--- a/src/streamlink/plugins/aliez.py
+++ b/src/streamlink/plugins/aliez.py
@@ -4,7 +4,7 @@ from os.path import splitext
 
 from streamlink.compat import urlparse, unquote
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream, RTMPStream
 
 _url_re = re.compile(r"""
@@ -44,7 +44,7 @@ class Aliez(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url, schema=_schema)
+        res = self.session.http.get(self.url, schema=_schema)
         streams = {}
         for url in res["urls"]:
             parsed = urlparse(url)
diff --git a/src/streamlink/plugins/aljazeeraen.py b/src/streamlink/plugins/aljazeeraen.py
index 38b2ab30..9d8431f6 100644
--- a/src/streamlink/plugins/aljazeeraen.py
+++ b/src/streamlink/plugins/aljazeeraen.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugins.brightcove import BrightcovePlayer
 from streamlink.stream import RTMPStream
 
@@ -17,7 +16,7 @@ class AlJazeeraEnglish(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         # check two different styles to include the video id in the page
         video_id_m = self.render_re.search(res.text) or self.video_id_re.search(res.text)
diff --git a/src/streamlink/plugins/animelab.py b/src/streamlink/plugins/animelab.py
index f106c977..4ef82fc8 100644
--- a/src/streamlink/plugins/animelab.py
+++ b/src/streamlink/plugins/animelab.py
@@ -3,7 +3,6 @@ import re
 from pprint import pprint
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream
 from streamlink.utils import parse_json
@@ -56,7 +55,7 @@ class AnimeLab(Plugin):
 
     def login(self, email, password):
         self.logger.debug("Attempting to log in as {0}", email)
-        res = http.post(self.login_url,
+        res = self.session.http.post(self.login_url,
                         data=dict(email=email, password=password),
                         allow_redirects=False,
                         raise_for_status=False)
@@ -79,7 +78,7 @@ class AnimeLab(Plugin):
 
         if self.login(email, password):
             self.logger.info("Successfully logged in as {0}", email)
-            video_collection = http.get(self.url, schema=self.video_collection_schema)
+            video_collection = self.session.http.get(self.url, schema=self.video_collection_schema)
             if video_collection["playlist"] is None or video_collection["position"] is None:
                 return
 
diff --git a/src/streamlink/plugins/antenna.py b/src/streamlink/plugins/antenna.py
index 950a1245..e53b5071 100644
--- a/src/streamlink/plugins/antenna.py
+++ b/src/streamlink/plugins/antenna.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HDSStream
 
 _url_re = re.compile(r"(http(s)?://(\w+\.)?antenna.gr)/webtv/watch\?cid=.+")
@@ -23,14 +22,14 @@ class Antenna(Plugin):
         root = match.group(1)
 
         # Download main URL
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         # Find playlist
         match = _playlist_re.search(res.text)
         playlist_url = root + match.group(1) + "d"
 
         # Download playlist
-        res = http.get(playlist_url)
+        res = self.session.http.get(playlist_url)
 
         # Find manifest
         match = _manifest_re.search(res.text)
diff --git a/src/streamlink/plugins/app17.py b/src/streamlink/plugins/app17.py
index 3b3373d6..25b3aa1e 100644
--- a/src/streamlink/plugins/app17.py
+++ b/src/streamlink/plugins/app17.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream, RTMPStream, HTTPStream
 
 API_URL = "https://api-dsa.17app.co/api/v1/liveStreams/getLiveStreamInfo"
@@ -20,10 +20,10 @@ class App17(Plugin):
         match = _url_re.match(self.url)
         channel = match.group("channel")
 
-        http.headers.update({'User-Agent': useragents.CHROME})
+        self.session.http.headers.update({'User-Agent': useragents.CHROME})
 
         payload = '{"liveStreamID": "%s"}' % (channel)
-        res = http.post(API_URL, data=payload)
+        res = self.session.http.post(API_URL, data=payload)
         status = _status_re.search(res.text)
         if not status:
             self.logger.info("Stream currently unavailable.")
diff --git a/src/streamlink/plugins/arconai.py b/src/streamlink/plugins/arconai.py
index 59fb1aea..8c60f5d4 100644
--- a/src/streamlink/plugins/arconai.py
+++ b/src/streamlink/plugins/arconai.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
@@ -21,7 +20,7 @@ class ArconaiTv(Plugin):
             'Referer': self.url
         }
 
-        res = http.get(self.url, headers=headers)
+        res = self.session.http.get(self.url, headers=headers)
 
         match = _playlist_re.search(res.text)
         if match is None:
diff --git a/src/streamlink/plugins/ard_live.py b/src/streamlink/plugins/ard_live.py
index ed49cbc7..e3a088f7 100644
--- a/src/streamlink/plugins/ard_live.py
+++ b/src/streamlink/plugins/ard_live.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HDSStream
 from streamlink.compat import urljoin
 from streamlink.stream import HTTPStream
@@ -33,10 +33,10 @@ class ard_live(Plugin):
         return cls._url_re.match(url) is not None
 
     def _get_streams(self):
-        data_url = http.get(self.url, schema=self._player_url_schema)
+        data_url = self.session.http.get(self.url, schema=self._player_url_schema)
         if data_url:
-            res = http.get(urljoin(self.url, data_url))
-            stream_info = http.xml(res, schema=self._livestream_schema)
+            res = self.session.http.get(urljoin(self.url, data_url))
+            stream_info = self.session.http.xml(res, schema=self._livestream_schema)
 
             for stream in stream_info:
                 url = stream["url"]
diff --git a/src/streamlink/plugins/ard_mediathek.py b/src/streamlink/plugins/ard_mediathek.py
index eb6495a7..511eb4b2 100644
--- a/src/streamlink/plugins/ard_mediathek.py
+++ b/src/streamlink/plugins/ard_mediathek.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream, HTTPStream
 
 MEDIA_URL = "http://www.ardmediathek.de/play/media/{0}"
@@ -69,8 +69,8 @@ class ard_mediathek(Plugin):
         return HLSStream.parse_variant_playlist(self.session, info["_stream"]).items()
 
     def _get_smil_streams(self, info):
-        res = http.get(info["_stream"])
-        smil = http.xml(res, "SMIL config", schema=_smil_schema)
+        res = self.session.http.get(info["_stream"])
+        smil = self.session.http.xml(res, "SMIL config", schema=_smil_schema)
 
         for video in smil["videos"]:
             url = "{0}/{1}{2}".format(smil["base"], video, HDCORE_PARAMETER)
@@ -80,7 +80,7 @@ class ard_mediathek(Plugin):
                 yield stream
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _media_id_re.search(res.text)
         if match:
             media_id = match.group(1)
@@ -89,8 +89,8 @@ class ard_mediathek(Plugin):
 
         self.logger.debug("Found media id: {0}", media_id)
 
-        res = http.get(MEDIA_URL.format(media_id))
-        media = http.json(res, schema=_media_schema)
+        res = self.session.http.get(MEDIA_URL.format(media_id))
+        media = self.session.http.json(res, schema=_media_schema)
 
         for media in media["_mediaArray"]:
             for stream in media["_mediaStreamArray"]:
diff --git a/src/streamlink/plugins/artetv.py b/src/streamlink/plugins/artetv.py
index d5360b7c..d90ac492 100644
--- a/src/streamlink/plugins/artetv.py
+++ b/src/streamlink/plugins/artetv.py
@@ -6,7 +6,6 @@ from itertools import chain
 
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream
 from streamlink.stream import HLSStream
@@ -93,8 +92,8 @@ class ArteTV(Plugin):
             json_url = JSON_LIVE_URL.format(language)
         else:
             json_url = JSON_VOD_URL.format(language, video_id)
-        res = http.get(json_url)
-        video = http.json(res, schema=_video_schema)
+        res = self.session.http.get(json_url)
+        video = self.session.http.json(res, schema=_video_schema)
 
         if not video["videoJsonPlayer"]["VSR"]:
             return
diff --git a/src/streamlink/plugins/atresplayer.py b/src/streamlink/plugins/atresplayer.py
index bc3348ce..27961a8b 100644
--- a/src/streamlink/plugins/atresplayer.py
+++ b/src/streamlink/plugins/atresplayer.py
@@ -5,7 +5,7 @@ import re
 from functools import partial
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate, StreamMapper
+from streamlink.plugin.api import validate, StreamMapper
 from streamlink.stream import HLSStream, DASHStream
 from streamlink.utils import parse_json, update_scheme, search_dict
 
@@ -45,10 +45,10 @@ class AtresPlayer(Plugin):
         super(AtresPlayer, self).__init__(update_scheme("https://", url))
 
     def _get_streams(self):
-        api_urls = http.get(self.url, schema=self.channel_id_schema)
+        api_urls = self.session.http.get(self.url, schema=self.channel_id_schema)
         for api_url in api_urls:
             log.debug("API URL: {0}".format(api_url))
-            for source in http.get(api_url, schema=self.stream_schema):
+            for source in self.session.http.get(api_url, schema=self.stream_schema):
                 log.debug("Stream source: {0} ({1})".format(source['src'], source.get("type", "n/a")))
 
                 if "type" not in source or source["type"] == "application/vnd.apple.mpegurl":
diff --git a/src/streamlink/plugins/bbciplayer.py b/src/streamlink/plugins/bbciplayer.py
index 102e5a1e..8c79baf5 100644
--- a/src/streamlink/plugins/bbciplayer.py
+++ b/src/streamlink/plugins/bbciplayer.py
@@ -9,7 +9,6 @@ from hashlib import sha1
 from streamlink import PluginError
 from streamlink.compat import parse_qsl, urlparse
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream
 from streamlink.stream import HLSStream
@@ -134,14 +133,14 @@ class BBCiPlayer(Plugin):
         """
         log.debug("Looking for vpid on {0}", url)
         # Use pre-fetched page if available
-        res = res or http.get(url)
+        res = res or self.session.http.get(url)
         m = self.mediator_re.search(res.text)
         vpid = m and parse_json(m.group(1), schema=self.mediator_schema)
         return vpid
 
     def find_tvip(self, url, master=False):
         log.debug("Looking for {0} tvip on {1}", "master" if master else "", url)
-        res = http.get(url)
+        res = self.session.http.get(url)
         if master:
             m = self.tvip_master_re.search(res.text)
         else:
@@ -154,7 +153,7 @@ class BBCiPlayer(Plugin):
             url = self.api_url.format(vpid=vpid, vpid_hash=self._hash_vpid(vpid),
                                       platform=platform)
             log.debug("Info API request: {0}", url)
-            medias = http.get(url, schema=self.mediaselector_schema)
+            medias = self.session.http.get(url, schema=self.mediaselector_schema)
             for media in medias:
                 for connection in media["connection"]:
                     urls[connection.get("transferFormat")].add(connection["href"])
@@ -188,14 +187,14 @@ class BBCiPlayer(Plugin):
         :return: Whether authentication was successful
         :rtype: bool
         """
-        session_res = http.get(
+        session_res = self.session.http.get(
             self.session_url,
             params=dict(ptrt=ptrt_url)
         )
 
         http_nonce = self._extract_nonce(session_res)
 
-        res = http.post(
+        res = self.session.http.post(
             self.auth_url,
             params=dict(
                 ptrt=ptrt_url,
diff --git a/src/streamlink/plugins/beattv.py b/src/streamlink/plugins/beattv.py
index 2d89567f..c5643718 100644
--- a/src/streamlink/plugins/beattv.py
+++ b/src/streamlink/plugins/beattv.py
@@ -23,7 +23,7 @@ from streamlink.packages.flashmedia.tag import (
 )
 from streamlink.packages.flashmedia.types import U8, U16BE, U32BE
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import Stream, StreamIOIterWrapper
 from streamlink.stream.flvconcat import FLVTagConcat
 from streamlink.stream.segmented import (
@@ -286,14 +286,14 @@ class BeatTV(Plugin):
         return Plugin.stream_weight(key)
 
     def _get_stream_info(self, url):
-        res = http.get(url, headers=HEADERS)
+        res = self.session.http.get(url, headers=HEADERS)
         match = re.search(r"embed.swf\?p=(\d+)", res.text)
         if not match:
             return
         program = match.group(1)
-        res = http.get(BEAT_PROGRAM.format(program), headers=HEADERS)
+        res = self.session.http.get(BEAT_PROGRAM.format(program), headers=HEADERS)
 
-        return http.json(res, schema=_schema)
+        return self.session.http.json(res, schema=_schema)
 
     def _get_streams(self):
         info = self._get_stream_info(self.url)
diff --git a/src/streamlink/plugins/bfmtv.py b/src/streamlink/plugins/bfmtv.py
index fcdc1410..395fb79c 100644
--- a/src/streamlink/plugins/bfmtv.py
+++ b/src/streamlink/plugins/bfmtv.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugins.brightcove import BrightcovePlayer
 from streamlink.stream import HLSStream
 
@@ -18,7 +17,7 @@ class BFMTV(Plugin):
 
     def _get_streams(self):
         # Retrieve URL page and search for Brightcove video data
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text)
         if match is not None:
             account_id = match.group('account_id')
diff --git a/src/streamlink/plugins/bigo.py b/src/streamlink/plugins/bigo.py
index 9aaed608..44160370 100644
--- a/src/streamlink/plugins/bigo.py
+++ b/src/streamlink/plugins/bigo.py
@@ -2,7 +2,7 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
 log = logging.getLogger(__name__)
@@ -19,7 +19,7 @@ class Bigo(Plugin):
         return cls._url_re.match(url) is not None
 
     def _get_streams(self):
-        page = http.get(self.url,
+        page = self.session.http.get(self.url,
                         allow_redirects=True,
                         headers={"User-Agent": useragents.IPHONE_6})
         videomatch = self._video_re.search(page.text)
diff --git a/src/streamlink/plugins/bilibili.py b/src/streamlink/plugins/bilibili.py
index 1ed5441e..4e3c068e 100644
--- a/src/streamlink/plugins/bilibili.py
+++ b/src/streamlink/plugins/bilibili.py
@@ -4,7 +4,7 @@ import time
 
 from requests.adapters import HTTPAdapter
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.stream import HTTPStream
 
 API_URL = "http://live.bilibili.com/api/playurl?cid={0}&player=1&quality=0&sign={1}&otype=json"
@@ -46,12 +46,12 @@ class Bilibili(Plugin):
         return Plugin.stream_weight(stream)
 
     def _get_streams(self):
-        http.mount('https://', HTTPAdapter(max_retries=99))
-        http.headers.update({'user-agent': useragents.CHROME})
+        self.session.http.mount('https://', HTTPAdapter(max_retries=99))
+        self.session.http.headers.update({'user-agent': useragents.CHROME})
         match = _url_re.match(self.url)
         channel = match.group("channel")
-        res_room_id = http.get(ROOM_API.format(channel))
-        room_id_json = http.json(res_room_id, schema=_room_id_schema)
+        res_room_id = self.session.http.get(ROOM_API.format(channel))
+        room_id_json = self.session.http.json(res_room_id, schema=_room_id_schema)
         room_id = room_id_json['room_id']
         if room_id_json['live_status'] != SHOW_STATUS_ONLINE:
             return
@@ -59,8 +59,8 @@ class Bilibili(Plugin):
         ts = int(time.time() / 60)
         sign = hashlib.md5(("{0}{1}".format(channel, API_SECRET, ts)).encode("utf-8")).hexdigest()
 
-        res = http.get(API_URL.format(room_id, sign))
-        room = http.json(res)
+        res = self.session.http.get(API_URL.format(room_id, sign))
+        room = self.session.http.json(res)
         if not room:
             return
 
diff --git a/src/streamlink/plugins/bloomberg.py b/src/streamlink/plugins/bloomberg.py
index d9fa989e..638151a6 100644
--- a/src/streamlink/plugins/bloomberg.py
+++ b/src/streamlink/plugins/bloomberg.py
@@ -2,7 +2,7 @@ from functools import partial
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream, HTTPStream
 from streamlink.utils import parse_json, update_scheme
 
@@ -88,14 +88,14 @@ class Bloomberg(Plugin):
         channel = match.group('channel')
 
         # Retrieve live player URL
-        res = http.get(self.PLAYER_URL)
+        res = self.session.http.get(self.PLAYER_URL)
         match = self._live_player_re.search(res.text)
         if match is None:
             return []
         live_player_url = update_scheme(self.url, match.group('live_player_url'))
 
         # Extract streams from the live player page
-        res = http.get(live_player_url)
+        res = self.session.http.get(live_player_url)
         stream_datas = re.findall(r'{0}(?:_MINI)?:({{.+?}}]}}]}})'.format(self.CHANNEL_MAP[channel]), res.text)
         streams = []
         for s in stream_datas:
@@ -107,14 +107,14 @@ class Bloomberg(Plugin):
 
     def _get_vod_streams(self):
         # Retrieve URL page and search for video ID
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._video_id_re.search(res.text)
         if match is None:
             return []
         video_id = match.group('video_id')
 
-        res = http.get(self.VOD_API_URL.format(video_id))
-        streams = http.json(res, schema=self._vod_api_schema)
+        res = self.session.http.get(self.VOD_API_URL.format(video_id))
+        streams = self.session.http.json(res, schema=self._vod_api_schema)
         return streams
 
     def _get_streams(self):
diff --git a/src/streamlink/plugins/bongacams.py b/src/streamlink/plugins/bongacams.py
index b2787cb3..8d87dd83 100644
--- a/src/streamlink/plugins/bongacams.py
+++ b/src/streamlink/plugins/bongacams.py
@@ -3,7 +3,7 @@ import re
 
 from streamlink.compat import urljoin, urlparse, urlunparse
 from streamlink.exceptions import PluginError, NoStreamsError
-from streamlink.plugin.api import validate, http, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.plugin import Plugin
 from streamlink.stream import HLSStream
 from streamlink.utils import update_scheme
@@ -44,12 +44,11 @@ class bongacams(Plugin):
         stream_page_path = match.group(5)
         country_code = CONST_DEFAULT_COUNTRY_CODE
 
-        # create http session and set headers
-        http_session = http
-        http_session.headers.update(CONST_HEADERS)
+        # update headers
+        self.session.http.headers.update(CONST_HEADERS)
 
         # get cookies
-        r = http_session.get(urlunparse((stream_page_scheme, stream_page_domain, stream_page_path, '', '', '')))
+        r = self.session.http.get(urlunparse((stream_page_scheme, stream_page_domain, stream_page_path, '', '', '')))
 
         # redirect to profile page means stream is offline
         if '/profile/' in r.url:
@@ -57,7 +56,7 @@ class bongacams(Plugin):
         if not r.ok:
             self.logger.debug("Status code for {0}: {1}", r.url, r.status_code)
             raise NoStreamsError(self.url)
-        if len(http_session.cookies) == 0:
+        if len(self.session.http.cookies) == 0:
             raise PluginError("Can't get a cookies")
 
         if urlparse(r.url).netloc != stream_page_domain:
@@ -79,11 +78,11 @@ class bongacams(Plugin):
         data = 'method=getRoomData&args%5B%5D={0}&args%5B%5D=false'.format(stream_page_path)
         self.logger.debug('DATA: {0}'.format(str(data)))
         # send request and close http-session
-        r = http_session.post(url=amf_gateway_url,
+        r = self.session.http.post(url=amf_gateway_url,
                               headers=headers,
                               params={CONST_AMF_GATEWAY_PARAM: country_code},
                               data=data)
-        http_session.close()
+        self.session.http.close()
 
         if r.status_code != 200:
             raise PluginError("unexpected status code for {0}: {1}", r.url, r.status_code)
diff --git a/src/streamlink/plugins/brightcove.py b/src/streamlink/plugins/brightcove.py
index 8b230895..06d95d53 100644
--- a/src/streamlink/plugins/brightcove.py
+++ b/src/streamlink/plugins/brightcove.py
@@ -7,7 +7,7 @@ from streamlink import PluginError
 from streamlink.packages.flashmedia import AMFMessage, AMFPacket
 from streamlink.packages.flashmedia.types import AMF3ObjectBase
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.stream import HLSStream, HTTPStream, RTMPStream
 from streamlink.compat import urlparse, parse_qsl, urlencode
 
@@ -74,17 +74,17 @@ class BrightcovePlayer(object):
         url = "{base}accounts/{account_id}/videos/{video_id}".format(base=self.api_url,
                                                                      account_id=self.account_id,
                                                                      video_id=video_id)
-        res = http.get(url,
+        res = self.session.http.get(url,
                        headers={
                            "User-Agent": useragents.CHROME,
                            "Referer": self.player_url(video_id),
                            "Accept": "application/json;pk={0}".format(policy_key)
                        })
-        return http.json(res, schema=self.schema)
+        return self.session.http.json(res, schema=self.schema)
 
     def policy_key(self, video_id):
         # Get the embedded player page
-        res = http.get(self.player_url(video_id))
+        res = self.session.http.get(self.player_url(video_id))
 
         policy_key_m = self.policy_key_re.search(res.text)
         policy_key = policy_key_m and policy_key_m.group("key")
@@ -151,7 +151,7 @@ class BrightcovePlayer(object):
         amf_packet = AMFPacket(version=3)
         amf_packet.messages.append(amf_message)
 
-        res = http.post(cls.amf_broker,
+        res = self.session.http.post(cls.amf_broker,
                         headers={"Content-Type": "application/x-amf"},
                         data=amf_packet.serialize(),
                         params=dict(playerKey=player_key),
diff --git a/src/streamlink/plugins/brittv.py b/src/streamlink/plugins/brittv.py
index 18a6dff0..287de77c 100644
--- a/src/streamlink/plugins/brittv.py
+++ b/src/streamlink/plugins/brittv.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.compat import urljoin
 from streamlink.stream import HLSStream
@@ -18,13 +17,13 @@ class BritTV(Plugin):
 
     @Plugin.broken()
     def _get_streams(self):
-        http.headers.update({"User-Agent": useragents.CHROME})
-        res = http.get(self.url)
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
+        res = self.session.http.get(self.url)
         m = self.js_re.search(res.text)
         if m:
             self.logger.debug("Found js key: {0}", m.group(1))
             js_url = m.group(0)
-            res = http.get(urljoin(self.url, js_url), headers={"Referer": self.url})
+            res = self.session.http.get(urljoin(self.url, js_url), headers={"Referer": self.url})
 
             self.logger.debug("Looking for stream URL...")
             for _, url in self.player_re.findall(res.text):
diff --git a/src/streamlink/plugins/btsports.py b/src/streamlink/plugins/btsports.py
index cd90b03e..30cd594f 100644
--- a/src/streamlink/plugins/btsports.py
+++ b/src/streamlink/plugins/btsports.py
@@ -4,7 +4,7 @@ from uuid import uuid4
 
 from streamlink.compat import quote
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.utils import url_equal
 
@@ -40,7 +40,7 @@ class BTSports(Plugin):
 
     def __init__(self, url):
         super(BTSports, self).__init__(url)
-        http.headers = {"User-Agent": useragents.FIREFOX}
+        self.session.http.headers = {"User-Agent": useragents.FIREFOX}
 
     @classmethod
     def can_handle_url(cls, url):
@@ -60,22 +60,22 @@ class BTSports(Plugin):
             "USER": username,
             "PASSWORD": password}
 
-        res = http.post(self.login_url, data=data)
+        res = self.session.http.post(self.login_url, data=data)
 
         self.logger.debug("Redirected to: {0}".format(res.url))
 
 
         if url_equal(res.url, self.url, ignore_scheme=True):
             self.logger.debug("Login successful, getting SAML token")
-            res = http.get("https://samlfed.bt.com/sportgetfedwebhls?bt.cid={0}".format(self.acid()))
+            res = self.session.http.get("https://samlfed.bt.com/sportgetfedwebhls?bt.cid={0}".format(self.acid()))
             d = self.saml_re.search(res.text)
             if d:
                 saml_data = d.group(1)
                 self.logger.debug("BT Sports federated login...")
-                res = http.post(self.api_url,
+                res = self.session.http.post(self.api_url,
                                 params={"action": "LoginBT", "channel": "WEBHLS", "bt.cid": self.acid},
                                 data={"SAMLResponse": saml_data})
-                fed_json = http.json(res)
+                fed_json = self.session.http.json(res)
                 success = fed_json['resultCode'] == "OK"
                 if not success:
                     self.logger.error("Failed to login: {0} - {1}".format(fed_json['errorDescription'],
@@ -102,15 +102,15 @@ class BTSports(Plugin):
              "bt.cid": self.acid(),
              "_": int(time.time())}
 
-        res = http.get(self.api_url, params=d, headers={"Accept": "application/json"})
-        return http.json(res)
+        res = self.session.http.get(self.api_url, params=d, headers={"Accept": "application/json"})
+        return self.session.http.json(res)
 
     def _get_streams(self):
         if self.options.get("email") and self.options.get("password"):
             if self.login(self.options.get("email"), self.options.get("password")):
                 self.logger.debug("Logged in and authenticated with BT Sports.")
 
-                res = http.get(self.url)
+                res = self.session.http.get(self.url)
                 m = self.content_re.findall(res.text)
                 if m:
                     info = dict(m)
diff --git a/src/streamlink/plugins/btv.py b/src/streamlink/plugins/btv.py
index 96661262..a795dcc8 100644
--- a/src/streamlink/plugins/btv.py
+++ b/src/streamlink/plugins/btv.py
@@ -3,7 +3,6 @@ import re
 
 from streamlink import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
@@ -54,14 +53,14 @@ class BTV(Plugin):
         return cls.url_re.match(url) is not None
 
     def login(self, username, password):
-        res = http.post(self.login_url, data={"username": username, "password": password})
+        res = self.session.http.post(self.login_url, data={"username": username, "password": password})
         if "success_logged_in" in res.text:
             return True
         else:
             return False
 
     def get_hls_url(self, media_id):
-        res = http.get(self.api_url, params=dict(media_id=media_id))
+        res = self.session.http.get(self.api_url, params=dict(media_id=media_id))
         try:
             return parse_json(res.text, schema=self.api_schema)
         except PluginError:
@@ -72,7 +71,7 @@ class BTV(Plugin):
             self.logger.error("BTV requires registration, set the username and password"
                               " with --btv-username and --btv-password")
         elif self.login(self.options.get("username"), self.options.get("password")):
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
             media_match = self.media_id_re.search(res.text)
             media_id = media_match and media_match.group(1)
             if media_id:
diff --git a/src/streamlink/plugins/cam4.py b/src/streamlink/plugins/cam4.py
index 4b4813f7..0e301f72 100644
--- a/src/streamlink/plugins/cam4.py
+++ b/src/streamlink/plugins/cam4.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream, RTMPStream
 from streamlink.utils import parse_json
 
@@ -28,7 +28,7 @@ class Cam4(Plugin):
         return Cam4._url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url, headers={'User-Agent': useragents.ANDROID})
+        res = self.session.http.get(self.url, headers={'User-Agent': useragents.ANDROID})
         match = self._video_data_re.search(res.text)
         if match is None:
             return
diff --git a/src/streamlink/plugins/camsoda.py b/src/streamlink/plugins/camsoda.py
index 72c84554..5139a4e4 100644
--- a/src/streamlink/plugins/camsoda.py
+++ b/src/streamlink/plugins/camsoda.py
@@ -2,7 +2,6 @@ import random
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
@@ -55,13 +54,13 @@ class Camsoda(Plugin):
         return True
 
     def _get_api_user(self, username):
-        res = http.get(self.API_URL_USER.format(username), headers=self.headers)
-        data_user = http.json(res, schema=_api_user_schema)
+        res = self.session.http.get(self.API_URL_USER.format(username), headers=self.headers)
+        data_user = self.session.http.json(res, schema=_api_user_schema)
         return data_user
 
     def _get_api_video(self, username):
-        res = http.get(self.API_URL_VIDEO.format(username, str(random.randint(1000, 99999))), headers=self.headers)
-        data_video = http.json(res, schema=_api_video_schema)
+        res = self.session.http.get(self.API_URL_VIDEO.format(username, str(random.randint(1000, 99999))), headers=self.headers)
+        data_video = self.session.http.json(res, schema=_api_video_schema)
         return data_video
 
     def _get_streams(self):
diff --git a/src/streamlink/plugins/canalplus.py b/src/streamlink/plugins/canalplus.py
index 8279ce0b..a0bba770 100644
--- a/src/streamlink/plugins/canalplus.py
+++ b/src/streamlink/plugins/canalplus.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HDSStream, HLSStream, HTTPStream
 
 
@@ -44,14 +44,14 @@ class CanalPlus(Plugin):
         video_id = match.group('video_id')
         if video_id is None:
             # Retrieve URL page and search for video ID
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
             match = self._video_id_re.search(res.text)
             if match is None:
                 return
             video_id = match.group('video_id')
 
-        res = http.get(self.API_URL.format(video_id))
-        videos = http.json(res, schema=self._api_schema)
+        res = self.session.http.get(self.API_URL.format(video_id))
+        videos = self.session.http.json(res, schema=self._api_schema)
         parsed = []
         headers = {'User-Agent': self._user_agent}
 
diff --git a/src/streamlink/plugins/cdnbg.py b/src/streamlink/plugins/cdnbg.py
index 794afd26..2c15eb2f 100644
--- a/src/streamlink/plugins/cdnbg.py
+++ b/src/streamlink/plugins/cdnbg.py
@@ -4,7 +4,6 @@ import re
 
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -50,13 +49,13 @@ class CDNBG(Plugin):
                     return url
 
     def _get_streams(self):
-        http.headers = {"User-Agent": useragents.CHROME}
-        res = http.get(self.url)
+        self.session.http.headers = {"User-Agent": useragents.CHROME}
+        res = self.session.http.get(self.url)
         iframe_url = self.find_iframe(res)
 
         if iframe_url:
             self.logger.debug("Found iframe: {0}", iframe_url)
-            res = http.get(iframe_url, headers={"Referer": self.url})
+            res = self.session.http.get(iframe_url, headers={"Referer": self.url})
             stream_url = update_scheme(self.url, self.stream_schema.validate(res.text))
             return HLSStream.parse_variant_playlist(self.session,
                                                     stream_url,
diff --git a/src/streamlink/plugins/ceskatelevize.py b/src/streamlink/plugins/ceskatelevize.py
index 37ae76b3..4eaa16d8 100644
--- a/src/streamlink/plugins/ceskatelevize.py
+++ b/src/streamlink/plugins/ceskatelevize.py
@@ -14,7 +14,7 @@ Additionally, videos from iVysilani archive should work as well.
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.exceptions import PluginError
 
@@ -91,7 +91,7 @@ class Ceskatelevize(Plugin):
 
     def _get_streams(self):
         # fetch requested url and find playlist info
-        response = http.get(self.url)
+        response = self.session.http.get(self.url)
         info = _find_playlist_info(response)
 
         if not info:
@@ -101,7 +101,7 @@ class Ceskatelevize(Plugin):
                 raise PluginError('Cannot find playlist info or player url!')
 
             # get player url and try to find playlist info in it
-            response = http.get(player_url)
+            response = self.session.http.get(player_url)
             info = _find_playlist_info(response)
             if not info:
                 raise PluginError('Cannot find playlist info in the player url!')
@@ -118,20 +118,20 @@ class Ceskatelevize(Plugin):
         }
 
         # fetch playlist url
-        response = http.post(
+        response = self.session.http.post(
             'http://www.ceskatelevize.cz/ivysilani/ajax/get-client-playlist',
             data=data,
             headers=headers
         )
-        json_data = http.json(response, schema=_playlist_url_schema)
+        json_data = self.session.http.json(response, schema=_playlist_url_schema)
 
         if json_data['url'] == "error_region":
             self.logger.error("This stream is not available in your territory")
             return
 
         # fetch playlist
-        response = http.post(json_data['url'])
-        json_data = http.json(response, schema=_playlist_schema)
+        response = self.session.http.post(json_data['url'])
+        json_data = self.session.http.json(response, schema=_playlist_schema)
         playlist = json_data['playlist'][0]['streamUrls']['main']
         return HLSStream.parse_variant_playlist(self.session, playlist)
 
diff --git a/src/streamlink/plugins/chaturbate.py b/src/streamlink/plugins/chaturbate.py
index 1d372ecc..e9887a31 100644
--- a/src/streamlink/plugins/chaturbate.py
+++ b/src/streamlink/plugins/chaturbate.py
@@ -2,7 +2,6 @@ import re
 import uuid
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -43,8 +42,8 @@ class Chaturbate(Plugin):
 
         post_data = "room_slug={0}&bandwidth=high".format(username)
 
-        res = http.post(API_HLS, headers=headers, cookies=cookies, data=post_data)
-        data = http.json(res, schema=_post_schema)
+        res = self.session.http.post(API_HLS, headers=headers, cookies=cookies, data=post_data)
+        data = self.session.http.json(res, schema=_post_schema)
 
         self.logger.info("Stream status: {0}".format(data["room_status"]))
         if (data["success"] is True and data["room_status"] == "public" and data["url"]):
diff --git a/src/streamlink/plugins/cinergroup.py b/src/streamlink/plugins/cinergroup.py
index 32625ca4..98a5de77 100644
--- a/src/streamlink/plugins/cinergroup.py
+++ b/src/streamlink/plugins/cinergroup.py
@@ -4,7 +4,6 @@ import json
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.compat import unquote
@@ -46,7 +45,7 @@ class CinerGroup(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         stream_url = self.stream_data_schema.validate(res.text)
         if stream_url:
             return HLSStream.parse_variant_playlist(self.session, stream_url)
diff --git a/src/streamlink/plugins/cnews.py b/src/streamlink/plugins/cnews.py
index 824d4d3f..5e6f4330 100644
--- a/src/streamlink/plugins/cnews.py
+++ b/src/streamlink/plugins/cnews.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 
 
 class CNEWS(Plugin):
@@ -15,7 +15,7 @@ class CNEWS(Plugin):
 
     def _get_streams(self):
         # Retrieve URL page and search for Dailymotion URL
-        res = http.get(self.url, headers={'User-Agent': useragents.CHROME})
+        res = self.session.http.get(self.url, headers={'User-Agent': useragents.CHROME})
         match = self._embed_live_url_re.search(res.text) or self._embed_video_url_re.search(res.text)
         if match is not None:
             return self.session.streams(match.group('dm_url'))
diff --git a/src/streamlink/plugins/crunchyroll.py b/src/streamlink/plugins/crunchyroll.py
index 76fb2634..b3498c27 100644
--- a/src/streamlink/plugins/crunchyroll.py
+++ b/src/streamlink/plugins/crunchyroll.py
@@ -1,13 +1,11 @@
 import argparse
 import datetime
-import random
 import re
-import string
 import logging
 from uuid import uuid4
 
 from streamlink.plugin import Plugin, PluginError, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 log = logging.getLogger(__name__)
@@ -107,12 +105,13 @@ class CrunchyrollAPI(object):
     _access_token = "Scwg9PRRZ19iVwD"
     _access_type = "com.crunchyroll.crunchyroid"
 
-    def __init__(self, cache, session_id=None, locale=_default_locale):
+    def __init__(self, cache, session, session_id=None, locale=_default_locale):
         """Abstract the API to access to Crunchyroll data.
 
         Can take saved credentials to use on it's calls to the API.
         """
         self.cache = cache
+        self.session = session
         self.session_id = session_id
         if self.session_id:  # if the session ID is setup don't use the cached auth token
             self.auth = None
@@ -162,8 +161,8 @@ class CrunchyrollAPI(object):
             params["session_id"] = self.session_id
 
         # The certificate used by Crunchyroll cannot be verified in some environments.
-        res = http.post(url, data=params, headers=self.headers, verify=False)
-        json_res = http.json(res, schema=_api_schema)
+        res = self.session.http.post(url, data=params, headers=self.headers, verify=False)
+        json_res = self.session.http.json(res, schema=_api_schema)
 
         if json_res["error"]:
             err_msg = json_res.get("message", "Unknown error")
@@ -183,7 +182,6 @@ class CrunchyrollAPI(object):
         log.debug("Device ID: {0}".format(device_id))
         return device_id
 
-
     def start_session(self):
         """
             Starts a session against Crunchyroll's server.
@@ -354,7 +352,10 @@ class Crunchyroll(Plugin):
 
         # use the crunchyroll locale as an override, for backwards compatibility
         locale = self.get_option("locale") or self.session.localization.language_code
-        api = CrunchyrollAPI(self.cache, session_id=self.get_option("session_id"), locale=locale)
+        api = CrunchyrollAPI(self.cache,
+                             self.session,
+                             session_id=self.get_option("session_id"),
+                             locale=locale)
 
         if not self.get_option("session_id"):
             self.logger.debug("Creating session with locale: {0}", locale)
diff --git a/src/streamlink/plugins/cybergame.py b/src/streamlink/plugins/cybergame.py
index d73ef616..57e6377b 100644
--- a/src/streamlink/plugins/cybergame.py
+++ b/src/streamlink/plugins/cybergame.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream
 
 LIVE_STREAM_URL = "rtmp://stream1.cybergame.tv:2936/live/"
@@ -51,8 +51,8 @@ class Cybergame(Plugin):
         return _url_re.match(url)
 
     def _get_playlist(self, **params):
-        res = http.get(PLAYLIST_URL, params=params)
-        playlist = http.xml(res, schema=_playlist_schema)
+        res = self.session.http.get(PLAYLIST_URL, params=params)
+        playlist = self.session.http.xml(res, schema=_playlist_schema)
         streams = {}
         for video in playlist["videos"]:
             name = "{0}p".format(video["height"])
diff --git a/src/streamlink/plugins/dailymotion.py b/src/streamlink/plugins/dailymotion.py
index 1557b98d..c1178e06 100644
--- a/src/streamlink/plugins/dailymotion.py
+++ b/src/streamlink/plugins/dailymotion.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.exceptions import NoStreamsError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream
 
 COOKIES = {
@@ -51,8 +51,8 @@ class DailyMotion(Plugin):
         return _url_re.match(url)
 
     def _get_streams_from_media(self, media_id):
-        res = http.get(STREAM_INFO_URL.format(media_id), cookies=COOKIES)
-        media = http.json(res, schema=_media_schema)
+        res = self.session.http.get(STREAM_INFO_URL.format(media_id), cookies=COOKIES)
+        media = self.session.http.json(res, schema=_media_schema)
 
         if media.get("error"):
             self.logger.error("Failed to get stream: {0}".format(media["error"]["title"]))
@@ -80,13 +80,13 @@ class DailyMotion(Plugin):
         }
         api_user_videos = USER_INFO_URL.format(username) + "/videos"
         try:
-            res = http.get(api_user_videos.format(username),
+            res = self.session.http.get(api_user_videos.format(username),
                            params=params)
         except Exception as e:
             self.logger.error("invalid username")
             raise NoStreamsError(self.url)
 
-        data = http.json(res, schema=_live_id_schema)
+        data = self.session.http.json(res, schema=_live_id_schema)
         if data["total"] > 0:
             media_id = data["list"][0]["id"]
             return media_id
diff --git a/src/streamlink/plugins/deutschewelle.py b/src/streamlink/plugins/deutschewelle.py
index c89bafd5..fbb7918e 100644
--- a/src/streamlink/plugins/deutschewelle.py
+++ b/src/streamlink/plugins/deutschewelle.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.compat import urlparse, parse_qsl
 from streamlink.stream import HLSStream, HTTPStream, RTMPStream
@@ -103,8 +102,8 @@ class DeutscheWelle(Plugin):
         yield self._create_stream(stream_url, default_quality)
 
         # Retrieve streams using API
-        res = http.get(self.smil_api_url.format(stream_api_id))
-        videos = http.xml(res, schema=self.smil_schema)
+        res = self.session.http.get(self.smil_api_url.format(stream_api_id))
+        videos = self.session.http.xml(res, schema=self.smil_schema)
 
         for video in videos['streams']:
             url = videos["base"] + video["src"]
@@ -121,7 +120,7 @@ class DeutscheWelle(Plugin):
             yield self._create_stream(url, quality)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.vod_player_type_re.search(res.text)
         if m is None:
             return
diff --git a/src/streamlink/plugins/dingittv.py b/src/streamlink/plugins/dingittv.py
index c756c9e5..af1efe63 100644
--- a/src/streamlink/plugins/dingittv.py
+++ b/src/streamlink/plugins/dingittv.py
@@ -1,6 +1,5 @@
 import re
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -43,12 +42,12 @@ class DingitTV(Plugin):
     def _get_streams(self):
         match = self.url_re.match(self.url)
 
-        res = http.post(self.flashvars_url,
+        res = self.session.http.post(self.flashvars_url,
                         data=dict(
                             broadcaster=match.group("broadcaster") or "Verm",
                             stream_id=match.group("channel_id") or match.group("highlight_id")))
 
-        flashvars = http.json(res, schema=self.flashvars_schema)
+        flashvars = self.session.http.json(res, schema=self.flashvars_schema)
 
         if flashvars.get("pereakaurl"):
             url = self.pereakaurl.format(flashvars.get("pereakaurl").strip("/"))
diff --git a/src/streamlink/plugins/dogan.py b/src/streamlink/plugins/dogan.py
index 844b79e4..17248553 100644
--- a/src/streamlink/plugins/dogan.py
+++ b/src/streamlink/plugins/dogan.py
@@ -5,7 +5,6 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -44,7 +43,7 @@ class Dogan(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_content_id(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         # find the contentId
         content_id_m = self.content_id_re.search(res.text)
         if content_id_m:
@@ -75,9 +74,9 @@ class Dogan(Plugin):
         else:
             api_url = urljoin(self.url, self.content_api.format(id=content_id))
 
-        apires = http.get(api_url)
+        apires = self.session.http.get(api_url)
 
-        stream_data = http.json(apires, schema=self.content_api_schema)
+        stream_data = self.session.http.json(apires, schema=self.content_api_schema)
         d = stream_data["Media"]["Link"]
         return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]), d["SecurePath"])
 
diff --git a/src/streamlink/plugins/dogus.py b/src/streamlink/plugins/dogus.py
index b19e36f5..e5314137 100644
--- a/src/streamlink/plugins/dogus.py
+++ b/src/streamlink/plugins/dogus.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 from streamlink.utils import update_scheme
 
@@ -28,7 +27,7 @@ class Dogus(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         mobile_url_m = self.mobile_url_re.search(res.text)
 
         mobile_url = mobile_url_m and update_scheme(self.url, mobile_url_m.group("url"))
diff --git a/src/streamlink/plugins/dommune.py b/src/streamlink/plugins/dommune.py
index 9b773764..f27c8ed1 100644
--- a/src/streamlink/plugins/dommune.py
+++ b/src/streamlink/plugins/dommune.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 
 DATA_URL = "http://www.dommune.com/freedommunezero2012/live/data/data.json"
 
@@ -20,8 +20,8 @@ class Dommune(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(DATA_URL)
-        data = http.json(res, schema=_data_schema)
+        res = self.session.http.get(DATA_URL)
+        data = self.session.http.json(res, schema=_data_schema)
         video_id = data["channel"] or data["channel2"]
         if not video_id:
             return
diff --git a/src/streamlink/plugins/douyutv.py b/src/streamlink/plugins/douyutv.py
index a609ad06..e488f8ee 100644
--- a/src/streamlink/plugins/douyutv.py
+++ b/src/streamlink/plugins/douyutv.py
@@ -5,7 +5,7 @@ import hashlib
 from requests.adapters import HTTPAdapter
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.stream import HTTPStream, HLSStream, RTMPStream
 
 API_URL = "https://capi.douyucdn.cn/api/v1/{0}&auth={1}"
@@ -107,8 +107,8 @@ class Douyutv(Plugin):
         match = _url_re.match(self.url)
         subdomain = match.group("subdomain")
 
-        http.verify = False
-        http.mount('https://', HTTPAdapter(max_retries=99))
+        self.session.http.verify = False
+        self.session.http.mount('https://', HTTPAdapter(max_retries=99))
 
         if subdomain == 'v':
             vid = match.group("vid")
@@ -116,8 +116,8 @@ class Douyutv(Plugin):
                 "User-Agent": useragents.ANDROID,
                 "X-Requested-With": "XMLHttpRequest"
             }
-            res = http.get(VAPI_URL.format(vid), headers=headers)
-            room = http.json(res, schema=_vapi_schema)
+            res = self.session.http.get(VAPI_URL.format(vid), headers=headers)
+            room = self.session.http.json(res, schema=_vapi_schema)
             yield "source", HLSStream(self.session, room["video_url"])
             return
 
@@ -125,18 +125,18 @@ class Douyutv(Plugin):
         try:
             channel = int(channel)
         except ValueError:
-            channel = http.get(self.url, schema=_room_id_schema)
+            channel = self.session.http.get(self.url, schema=_room_id_schema)
             if channel is None:
-                channel = http.get(self.url, schema=_room_id_alt_schema)
+                channel = self.session.http.get(self.url, schema=_room_id_alt_schema)
 
-        http.headers.update({'User-Agent': useragents.WINDOWS_PHONE_8})
+        self.session.http.headers.update({'User-Agent': useragents.WINDOWS_PHONE_8})
         cdns = ["ws", "tct", "ws2", "dl"]
         ts = int(time.time())
         suffix = "room/{0}?aid=wp&cdn={1}&client_sys=wp&time={2}".format(channel, cdns[0], ts)
         sign = hashlib.md5((suffix + API_SECRET).encode()).hexdigest()
 
-        res = http.get(API_URL.format(suffix, sign))
-        room = http.json(res, schema=_room_schema)
+        res = self.session.http.get(API_URL.format(suffix, sign))
+        room = self.session.http.json(res, schema=_room_schema)
         if not room:
             self.logger.info("Not a valid room url.")
             return
diff --git a/src/streamlink/plugins/dplay.py b/src/streamlink/plugins/dplay.py
index 089613ba..ddef47be 100644
--- a/src/streamlink/plugins/dplay.py
+++ b/src/streamlink/plugins/dplay.py
@@ -6,7 +6,7 @@ import time
 from streamlink.compat import quote
 from streamlink.exceptions import PluginError, NoStreamsError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import StreamMapper, http, validate
+from streamlink.plugin.api import StreamMapper, validate
 from streamlink.stream import HLSStream, HDSStream
 
 # Interface URLs for Dplay
@@ -100,7 +100,7 @@ class Dplay (Plugin):
         hdr = {'User-Agent': USER_AGENT.format('sv_SE')}
 
         # Parse video ID from data received from supplied URL
-        res = http.get(self.url, headers=hdr).text
+        res = self.session.http.get(self.url, headers=hdr).text
         match = _videoid_re.search(res)
         if not match:   # Video ID not found
             self.logger.error('Failed to parse video ID')
@@ -108,8 +108,8 @@ class Dplay (Plugin):
         videoId = match.group('id')
 
         # Get data from general API to validate that stream is playable
-        res = http.get(GENERAL_API_URL.format(self.domain, videoId), headers=hdr)
-        data = http.json(res, schema=_api_schema)
+        res = self.session.http.get(GENERAL_API_URL.format(self.domain, videoId), headers=hdr)
+        data = self.session.http.json(res, schema=_api_schema)
         if not data['data']:                # No data item found
             self.logger.error('Unable to find "data" item in general API response')
             return {}
@@ -119,8 +119,8 @@ class Dplay (Plugin):
 
         # Get geo data, validate and form cookie consisting of
         # geo data + expiry timestamp (current time + 1 hour)
-        res = http.get(GEO_DATA_URL.format(self.domain), headers=hdr)
-        geo = http.json(res, schema=_geo_schema)
+        res = self.session.http.get(GEO_DATA_URL.format(self.domain), headers=hdr)
+        geo = self.session.http.json(res, schema=_geo_schema)
         timestamp = (int(time.time()) + 3600) * 1000
         cookie = 'dsc-geo=%s' % quote('{"countryCode":"%s","expiry":%s}' % (geo, timestamp))
 
@@ -129,13 +129,13 @@ class Dplay (Plugin):
 
         # Get available streams using stream API
         try:
-            res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hls'),
+            res = self.session.http.get(STREAM_API_URL.format(self.domain, videoId, 'hls'),
                            headers=hdr, verify=False)
-            data = http.json(res, schema=_media_schema)
+            data = self.session.http.json(res, schema=_media_schema)
             media = data.copy()
-            res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hds'),
+            res = self.session.http.get(STREAM_API_URL.format(self.domain, videoId, 'hds'),
                            headers=hdr, verify=False)
-            data = http.json(res, schema=_media_schema)
+            data = self.session.http.json(res, schema=_media_schema)
             media.update(data)
         except PluginError as err:      # Likely geo-restricted
             if any(e in str(err) for e in ('401 Client Error',
diff --git a/src/streamlink/plugins/drdk.py b/src/streamlink/plugins/drdk.py
index a366d05d..9182dd19 100644
--- a/src/streamlink/plugins/drdk.py
+++ b/src/streamlink/plugins/drdk.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HDSStream
 
 LIVE_CHANNELS_API_URL = "http://www.dr.dk/tv/external/channels?mediaType=tv"
@@ -97,8 +97,8 @@ class DRDK(Plugin):
             return self._get_vod_streams(match.group("program"))
 
     def _get_vod_streams(self, program):
-        res = http.get(VOD_API_URL.format(program))
-        video = http.json(res, schema=_video_schema)
+        res = self.session.http.get(VOD_API_URL.format(program))
+        video = self.session.http.json(res, schema=_video_schema)
 
         streams = {}
         for link in video:
@@ -114,8 +114,8 @@ class DRDK(Plugin):
         return streams
 
     def _get_live_streams(self, slug):
-        res = http.get(LIVE_CHANNELS_API_URL)
-        res = http.json(res, schema=_channels_schema)
+        res = self.session.http.get(LIVE_CHANNELS_API_URL)
+        res = self.session.http.json(res, schema=_channels_schema)
 
         for channel in filter(lambda c: c["Slug"] == slug, res):
             servers = channel["StreamingServers"]
diff --git a/src/streamlink/plugins/earthcam.py b/src/streamlink/plugins/earthcam.py
index 9791d1b0..1e62be35 100644
--- a/src/streamlink/plugins/earthcam.py
+++ b/src/streamlink/plugins/earthcam.py
@@ -3,7 +3,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, RTMPStream
 from streamlink.utils import parse_json, update_scheme
@@ -32,7 +31,7 @@ class EarthCam(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.cam_name_re.search(res.text)
         cam_name = m and m.group("name")
         json_base = self.cam_data_schema.validate(res.text)
diff --git a/src/streamlink/plugins/ellobo.py b/src/streamlink/plugins/ellobo.py
index 1fcc7a99..7f270410 100644
--- a/src/streamlink/plugins/ellobo.py
+++ b/src/streamlink/plugins/ellobo.py
@@ -3,7 +3,6 @@ import re
 from streamlink import NoPluginError
 from streamlink import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 
 
 class ElLobo(Plugin):
@@ -15,7 +14,7 @@ class ElLobo(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         # Search for the iframe in the page
         iframe_m = self.iframe_re.search(res.text)
 
diff --git a/src/streamlink/plugins/eltrecetv.py b/src/streamlink/plugins/eltrecetv.py
index c733c39c..9a336a29 100644
--- a/src/streamlink/plugins/eltrecetv.py
+++ b/src/streamlink/plugins/eltrecetv.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -16,9 +16,9 @@ class ElTreceTV(Plugin):
     def _get_streams(self):
         if "eltrecetv.com.ar/vivo" in self.url.lower():
             try:
-                http.headers = {'Referer': self.url,
+                self.session.http.headers = {'Referer': self.url,
                                 'User-Agent': useragents.ANDROID}
-                res = http.get('https://api.iamat.com/metadata/atcodes/eltrece')
+                res = self.session.http.get('https://api.iamat.com/metadata/atcodes/eltrece')
                 yt_id = parse_json(res.text)["atcodes"][0]["context"]["ahora"]["vivo"]["youtubeVideo"]
                 yt_url = "https://www.youtube.com/watch?v={0}".format(yt_id)
                 return self.session.streams(yt_url)
@@ -26,9 +26,9 @@ class ElTreceTV(Plugin):
                 self.logger.info("Live content is temporarily unavailable. Please try again later.")
         else:
             try:
-                http.headers = {'Referer': self.url,
+                self.session.http.headers = {'Referer': self.url,
                                 'User-Agent': useragents.CHROME}
-                res = http.get(self.url)
+                res = self.session.http.get(self.url)
                 _player_re = re.compile(r'''data-kaltura="([^"]+)"''')
                 match = _player_re.search(res.text)
                 if not match:
diff --git a/src/streamlink/plugins/eurocom.py b/src/streamlink/plugins/eurocom.py
index 65a5cf2f..ec6ecadf 100644
--- a/src/streamlink/plugins/eurocom.py
+++ b/src/streamlink/plugins/eurocom.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import RTMPStream
 
 
@@ -15,7 +14,7 @@ class Eurocom(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.file_re.search(res.text)
         if m:
             stream_url = m.group("url")
diff --git a/src/streamlink/plugins/euronews.py b/src/streamlink/plugins/euronews.py
index 45d88ed2..37fb6f41 100644
--- a/src/streamlink/plugins/euronews.py
+++ b/src/streamlink/plugins/euronews.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream
 
@@ -28,7 +27,7 @@ class Euronews(Plugin):
         Find the VOD video url
         :return: video url
         """
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         video_urls = self._re_vod.findall(res.text)
         if len(video_urls):
             return dict(vod=HTTPStream(self.session, video_urls[0]))
@@ -39,10 +38,10 @@ class Euronews(Plugin):
         :param subdomain:
         :return:
         """
-        res = http.get(self._live_api_url.format(subdomain))
-        live_res = http.json(res, schema=self._live_schema)
-        api_res = http.get(live_res[u"url"])
-        stream_data = http.json(api_res, schema=self._stream_api_schema)
+        res = self.session.http.get(self._live_api_url.format(subdomain))
+        live_res = self.session.http.json(res, schema=self._live_schema)
+        api_res = self.session.http.get(live_res[u"url"])
+        stream_data = self.session.http.json(api_res, schema=self._stream_api_schema)
         return HLSStream.parse_variant_playlist(self.session, stream_data[u'primary'])
 
     def _get_streams(self):
diff --git a/src/streamlink/plugins/europaplus.py b/src/streamlink/plugins/europaplus.py
index f7dae7fa..5c5d212a 100644
--- a/src/streamlink/plugins/europaplus.py
+++ b/src/streamlink/plugins/europaplus.py
@@ -3,7 +3,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HLSStream
 from streamlink.utils import update_scheme
@@ -18,10 +17,10 @@ class EuropaPlusTV(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         for iframe in itertags(res.text, "iframe"):
             self.logger.debug("Found iframe: {0}".format(iframe))
-            iframe_res = http.get(iframe.attributes['src'], headers={"Referer": self.url})
+            iframe_res = self.session.http.get(iframe.attributes['src'], headers={"Referer": self.url})
             m = self.src_re.search(iframe_res.text)
             surl = m and m.group("url")
             if surl:
diff --git a/src/streamlink/plugins/expressen.py b/src/streamlink/plugins/expressen.py
index 0ac5ccb1..b34f99b1 100644
--- a/src/streamlink/plugins/expressen.py
+++ b/src/streamlink/plugins/expressen.py
@@ -1,7 +1,6 @@
 import re
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HDSStream, HLSStream, RTMPStream
 
 
@@ -18,15 +17,15 @@ class Expressen(Plugin):
 
     @Plugin.broken()
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         match = _meta_xmlurl_id_re.search(res.text)
         if not match:
             return
 
         xml_info_url = STREAMS_INFO_URL.format(match.group(1))
-        video_info_res = http.get(xml_info_url)
-        parsed_info = http.xml(video_info_res)
+        video_info_res = self.session.http.get(xml_info_url)
+        parsed_info = self.session.http.xml(video_info_res)
 
         live_el = parsed_info.find("live")
         live = live_el is not None and live_el.text == "1"
diff --git a/src/streamlink/plugins/facebook.py b/src/streamlink/plugins/facebook.py
index 094090ed..1b5976e2 100644
--- a/src/streamlink/plugins/facebook.py
+++ b/src/streamlink/plugins/facebook.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import DASHStream, HTTPStream
 from streamlink.utils import parse_json
 
@@ -17,7 +17,7 @@ class Facebook(Plugin):
         return cls._url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url, headers={"User-Agent": useragents.CHROME})
+        res = self.session.http.get(self.url, headers={"User-Agent": useragents.CHROME})
 
         streams = {}
         vod_urls = set([])
diff --git a/src/streamlink/plugins/filmon.py b/src/streamlink/plugins/filmon.py
index 98d14c9b..68ed5711 100644
--- a/src/streamlink/plugins/filmon.py
+++ b/src/streamlink/plugins/filmon.py
@@ -4,7 +4,7 @@ import time
 
 from streamlink import StreamError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 
@@ -19,7 +19,7 @@ class FilmOnHLS(HLSStream):
         if self.channel is None and self.vod_id is None:
             raise ValueError("channel or vod_id must be set")
         self.quality = quality
-        self.api = FilmOnAPI()
+        self.api = FilmOnAPI(session_)
         self._url = None
         self.watch_timeout = 0
 
@@ -57,6 +57,9 @@ class FilmOnHLS(HLSStream):
 
 
 class FilmOnAPI(object):
+    def __init__(self, session):
+        self.session = session
+
     channel_url = "http://www.filmon.com/api-v2/channel/{0}?protocol=hls"
     vod_url = "http://www.filmon.com/vod/info/{0}"
 
@@ -78,12 +81,12 @@ class FilmOnAPI(object):
     )
 
     def channel(self, channel):
-        res = http.get(self.channel_url.format(channel))
-        return http.json(res, schema=self.api_schema)
+        res = self.session.http.get(self.channel_url.format(channel))
+        return self.session.http.json(res, schema=self.api_schema)
 
     def vod(self, vod_id):
-        res = http.get(self.vod_url.format(vod_id))
-        return http.json(res, schema=self.api_schema)
+        res = self.session.http.get(self.vod_url.format(vod_id))
+        return self.session.http.json(res, schema=self.api_schema)
 
 
 class Filmon(Plugin):
@@ -109,7 +112,7 @@ class Filmon(Plugin):
 
     def __init__(self, url):
         super(Filmon, self).__init__(url)
-        self.api = FilmOnAPI()
+        self.api = FilmOnAPI(self.session)
 
     @classmethod
     def can_handle_url(cls, url):
@@ -136,7 +139,7 @@ class Filmon(Plugin):
 
         else:
             if not channel:
-                channel = http.get(self.url, schema=self._channel_id_schema)
+                channel = self.session.http.get(self.url, schema=self._channel_id_schema)
                 self.logger.debug("Found channel ID: {0}", channel)
             data = self.api.channel(channel)
             for stream in data["streams"]:
diff --git a/src/streamlink/plugins/foxtr.py b/src/streamlink/plugins/foxtr.py
index 606bec26..31ab2803 100644
--- a/src/streamlink/plugins/foxtr.py
+++ b/src/streamlink/plugins/foxtr.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -19,7 +18,7 @@ class FoxTR(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self.playervars_re.search(res.text)
         if match:
             stream_url = match.group(1)
diff --git a/src/streamlink/plugins/funimationnow.py b/src/streamlink/plugins/funimationnow.py
index 2a4ee6e3..81b31d4c 100644
--- a/src/streamlink/plugins/funimationnow.py
+++ b/src/streamlink/plugins/funimationnow.py
@@ -6,7 +6,6 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import itertags
@@ -47,11 +46,11 @@ class Experience(object):
         headers = kwargs.pop("headers", {})
         if self.token:
             headers.update({"Authorization": "Token {0}".format(self.token)})
-            http.cookies.update({"src_token": self.token})
+            self.session.http.cookies.update({"src_token": self.token})
 
         log.debug("Making {0}request to {1}".format("authorized " if self.token else "", url))
 
-        return http.request(method, url, *args, headers=headers, **kwargs)
+        return self.session.http.request(method, url, *args, headers=headers, **kwargs)
 
     def get(self, *args, **kwargs):
         return self.request("GET", *args, **kwargs)
@@ -69,7 +68,7 @@ class Experience(object):
         api_url = self.show_api_url.format(experience_id=self.experience_id)
         log.debug("Requesting experience data: {0}".format(api_url))
         res = self.get(api_url)
-        data = http.json(res)
+        data = self.session.http.json(res)
         self.cache[self.experience_id] = data
 
     @property
@@ -126,10 +125,10 @@ class Experience(object):
         """
         api_url = self.sources_api_url.format(experience_id=self.experience_id)
         res = self.get(api_url, params={"pinst_id": self.pinst_id})
-        return http.json(res)
+        return self.session.http.json(res)
 
     def login_csrf(self):
-        r = http.get(self.login_url)
+        r = self.session.http.get(self.login_url)
         for input in itertags(r.text, "input"):
             if input.attributes.get("name") == self.CSRF_NAME:
                 return input.attributes.get("value")
@@ -140,7 +139,7 @@ class Experience(object):
                       data={'username': email, 'password': password, self.CSRF_NAME: self.login_csrf()},
                       raise_for_status=False,
                       headers={"Referer": "https://www.funimation.com/log-in/"})
-        d = http.json(r, schema=self.login_schema)
+        d = self.session.http.json(r, schema=self.login_schema)
         self.token = d.get("token", None)
         return self.token is not None
 
@@ -192,15 +191,15 @@ class FunimationNow(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        http.headers = {"User-Agent": useragents.CHROME}
-        res = http.get(self.url)
+        self.session.http.headers = {"User-Agent": useragents.CHROME}
+        res = self.session.http.get(self.url)
 
         # remap en to english, and ja to japanese
         rlanguage = {"en": "english", "ja": "japanese"}.get(self.get_option("language").lower(),
                                                             self.get_option("language").lower())
         if "_Incapsula_Resource" in res.text:
             self.bypass_incapsula(res)
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
 
         id_m = self.experience_id_re.search(res.text)
         experience_id = id_m and int(id_m.group(1))
@@ -276,7 +275,7 @@ class FunimationNow(Plugin):
             url = jsm and jsm.group(1)
             if url:
                 log.debug("Found Incapsula auth URL: {0}", url)
-                res = http.get(urljoin(self.url, url))
+                res = self.session.http.get(urljoin(self.url, url))
                 success = res.status_code == 200
                 if success:
                     self.save_cookies(lambda c: "incap" in c.name)
diff --git a/src/streamlink/plugins/gardenersworld.py b/src/streamlink/plugins/gardenersworld.py
index 9f42a5a1..f212740c 100644
--- a/src/streamlink/plugins/gardenersworld.py
+++ b/src/streamlink/plugins/gardenersworld.py
@@ -4,7 +4,6 @@ import re
 
 from streamlink import NoPluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.utils import update_scheme
 
 
@@ -17,7 +16,7 @@ class GardenersWorld(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         iframe = self.iframe_re.search(page.text)
         if iframe:
             self.logger.debug("Handing off of {0}".format(iframe.group("url")))
diff --git a/src/streamlink/plugins/garena.py b/src/streamlink/plugins/garena.py
index bc525892..fdc6d4e5 100644
--- a/src/streamlink/plugins/garena.py
+++ b/src/streamlink/plugins/garena.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -41,8 +40,8 @@ class Garena(Plugin):
         return _url_re.match(url)
 
     def _post_api(self, api, payload, schema):
-        res = http.post(api, json=payload)
-        data = http.json(res, schema=schema)
+        res = self.session.http.post(api, json=payload)
+        data = self.session.http.json(res, schema=schema)
 
         if data["result"] == "success":
             post_data = data["reply"]
diff --git a/src/streamlink/plugins/goltelevision.py b/src/streamlink/plugins/goltelevision.py
index 81e942cf..60c591d2 100644
--- a/src/streamlink/plugins/goltelevision.py
+++ b/src/streamlink/plugins/goltelevision.py
@@ -3,7 +3,7 @@ from __future__ import print_function, absolute_import
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -26,7 +26,7 @@ class GOLTelevision(Plugin):
 
     def _get_streams(self):
         return HLSStream.parse_variant_playlist(self.session,
-                                                http.get(self.api_url, schema=self.api_schema))
+                                                self.session.http.get(self.api_url, schema=self.api_schema))
 
 
 __plugin__ = GOLTelevision
diff --git a/src/streamlink/plugins/goodgame.py b/src/streamlink/plugins/goodgame.py
index 817cb5f2..209aef6f 100644
--- a/src/streamlink/plugins/goodgame.py
+++ b/src/streamlink/plugins/goodgame.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -24,7 +23,7 @@ class GoodGame(Plugin):
         return _url_re.match(url)
 
     def _check_stream(self, url):
-        res = http.get(url, acceptable_status=(200, 404))
+        res = self.session.http.get(url, acceptable_status=(200, 404))
         if res.status_code == 200:
             return True
 
@@ -32,13 +31,13 @@ class GoodGame(Plugin):
         headers = {
             "Referer": self.url
         }
-        res = http.get(self.url, headers=headers)
+        res = self.session.http.get(self.url, headers=headers)
 
         match = _ddos_re.search(res.text)
         if match:
             self.logger.debug("Anti-DDOS bypass...")
             headers["Cookie"] = match.group(1)
-            res = http.get(self.url, headers=headers)
+            res = self.session.http.get(self.url, headers=headers)
 
         match = _apidata_re.search(res.text)
         channel_info = match and parse_json(match.group("data"))
diff --git a/src/streamlink/plugins/googledrive.py b/src/streamlink/plugins/googledrive.py
index 6b354fde..bc1637ce 100644
--- a/src/streamlink/plugins/googledrive.py
+++ b/src/streamlink/plugins/googledrive.py
@@ -2,7 +2,6 @@ import re
 
 from streamlink.compat import parse_qsl
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HTTPStream
 
 
@@ -17,7 +16,7 @@ class GoogleDocs(Plugin):
     def _get_streams(self):
         docid = self.url_re.match(self.url).group(1)
         self.logger.debug("Google Docs ID: {0}", docid)
-        res = http.get(self.api_url, params=dict(docid=docid))
+        res = self.session.http.get(self.api_url, params=dict(docid=docid))
         data = dict(parse_qsl(res.text))
 
         if data["status"] == "ok":
diff --git a/src/streamlink/plugins/gulli.py b/src/streamlink/plugins/gulli.py
index 824fdeb9..f77dbf0a 100644
--- a/src/streamlink/plugins/gulli.py
+++ b/src/streamlink/plugins/gulli.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream
 from streamlink.utils import parse_json
 
@@ -43,7 +43,7 @@ class Gulli(Plugin):
             live = True
             player_url = self.LIVE_PLAYER_URL
 
-        res = http.get(player_url)
+        res = self.session.http.get(player_url)
         playlist = re.findall(self._playlist_re, res.text)
         index = 0
         if not live:
diff --git a/src/streamlink/plugins/hitbox.py b/src/streamlink/plugins/hitbox.py
index ddb45036..8ecc7fc3 100644
--- a/src/streamlink/plugins/hitbox.py
+++ b/src/streamlink/plugins/hitbox.py
@@ -4,7 +4,7 @@ from itertools import chain
 
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import StreamMapper, http, validate
+from streamlink.plugin.api import StreamMapper, validate
 from streamlink.stream import HLSStream, HTTPStream, RTMPStream
 from streamlink.utils import absolute_url
 
@@ -176,8 +176,8 @@ class Hitbox(Plugin):
         channel, media_id = match.group("channel", "media_id")
         self.logger.debug("Matched URL: channel={0}, media_id={1}".format(channel, media_id))
         if not media_id:
-            res = http.get(LIVE_API.format(channel))
-            livestream = http.json(res, schema=_live_schema)
+            res = self.session.http.get(LIVE_API.format(channel))
+            livestream = self.session.http.json(res, schema=_live_schema)
             if livestream.get("media_hosted_media"):
                 hosted = _live_schema.validate(livestream["media_hosted_media"])
                 self.logger.info("{0} is hosting {1}", livestream["media_user_name"], hosted["media_user_name"])
@@ -191,8 +191,8 @@ class Hitbox(Plugin):
         else:
             media_type = "video"
 
-        res = http.get(PLAYER_API.format(media_type, media_id))
-        player = http.json(res, schema=_player_schema)
+        res = self.session.http.get(PLAYER_API.format(media_type, media_id))
+        player = self.session.http.json(res, schema=_player_schema)
 
         if media_type == "live":
             return self._get_live_streams(player)
diff --git a/src/streamlink/plugins/huajiao.py b/src/streamlink/plugins/huajiao.py
index e0f13ce6..ee12cc88 100644
--- a/src/streamlink/plugins/huajiao.py
+++ b/src/streamlink/plugins/huajiao.py
@@ -8,7 +8,7 @@ import json
 from requests.adapters import HTTPAdapter
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import (HTTPStream, HLSStream)
 
 USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
@@ -45,17 +45,17 @@ class Huajiao(Plugin):
         match = _url_re.match(self.url)
         channel = match.group("channel")
 
-        http.headers.update({"User-Agent": USER_AGENT})
-        http.verify = False
+        self.session.http.headers.update({"User-Agent": USER_AGENT})
+        self.session.http.verify = False
 
-        feed_json = http.get(HUAJIAO_URL.format(channel), schema=_feed_json_schema)
+        feed_json = self.session.http.get(HUAJIAO_URL.format(channel), schema=_feed_json_schema)
         if feed_json['feed']['m3u8']:
             stream = HLSStream(self.session, feed_json['feed']['m3u8'])
         else:
             sn = feed_json['feed']['sn']
             channel_sid = feed_json['relay']['channel']
             sid = uuid.uuid4().hex.upper()
-            encoded_json = http.get(LAPI_URL.format(channel_sid, sn, sid, time.time(), random.random())).content
+            encoded_json = self.session.http.get(LAPI_URL.format(channel_sid, sn, sid, time.time(), random.random())).content
             decoded_json = base64.decodestring(encoded_json[0:3] + encoded_json[6:]).decode('utf-8')
             video_data = json.loads(decoded_json)
             stream = HTTPStream(self.session, video_data['main'])
diff --git a/src/streamlink/plugins/huomao.py b/src/streamlink/plugins/huomao.py
index 97de6737..aee762b3 100644
--- a/src/streamlink/plugins/huomao.py
+++ b/src/streamlink/plugins/huomao.py
@@ -14,7 +14,6 @@ and return each option to the user.
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HTTPStream
 
 # URL pattern for recognizing inputed Huomao.tv / Huomao.com URL.
@@ -90,7 +89,7 @@ class Huomao(Plugin):
 
     def _get_streams(self):
         room_id = url_re.search(self.url).group("room_id")
-        html = http.get(mobile_url.format(room_id))
+        html = self.session.http.get(mobile_url.format(room_id))
         stream_id = self.get_stream_id(html.text)
         stream_info = self.get_stream_info(html.text)
 
diff --git a/src/streamlink/plugins/huya.py b/src/streamlink/plugins/huya.py
index ea4ec66b..4109f6e1 100644
--- a/src/streamlink/plugins/huya.py
+++ b/src/streamlink/plugins/huya.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.plugin.api import useragents
 from streamlink.utils import update_scheme
@@ -34,10 +34,10 @@ class Huya(Plugin):
         match = _url_re.match(self.url)
         channel = match.group("channel")
 
-        http.headers.update({"User-Agent": useragents.IPAD})
+        self.session.http.headers.update({"User-Agent": useragents.IPAD})
         # Some problem with SSL on huya.com now, do not use https
 
-        hls_url = http.get(HUYA_URL % channel, schema=_hls_schema)
+        hls_url = self.session.http.get(HUYA_URL % channel, schema=_hls_schema)
         yield "live", HLSStream(self.session, update_scheme("http://", hls_url))
 
 
diff --git a/src/streamlink/plugins/idf1.py b/src/streamlink/plugins/idf1.py
index 4ba48f49..880ccf63 100644
--- a/src/streamlink/plugins/idf1.py
+++ b/src/streamlink/plugins/idf1.py
@@ -2,7 +2,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json, update_scheme
 
@@ -45,7 +45,7 @@ class IDF1(Plugin):
         return IDF1._url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._video_id_re.search(res.text) or self._video_id_alt_re.search(res.text)
         if match is None:
             return
@@ -53,8 +53,8 @@ class IDF1(Plugin):
         video_type = match.group('video_type')
         video_id = match.group('video_id')
 
-        videos = http.get(self.DACAST_API_URL.format(broadcaster_id, video_type, video_id), schema=self._api_schema)
-        token = http.get(self.DACAST_TOKEN_URL.format(broadcaster_id, video_type, video_id), schema=self._token_schema)
+        videos = self.session.http.get(self.DACAST_API_URL.format(broadcaster_id, video_type, video_id), schema=self._api_schema)
+        token = self.session.http.get(self.DACAST_TOKEN_URL.format(broadcaster_id, video_type, video_id), schema=self._token_schema)
         parsed = []
 
         for video_url in videos:
diff --git a/src/streamlink/plugins/ine.py b/src/streamlink/plugins/ine.py
index 1dbbf8ab..8ebc9109 100644
--- a/src/streamlink/plugins/ine.py
+++ b/src/streamlink/plugins/ine.py
@@ -4,7 +4,6 @@ import json
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream
 from streamlink.utils import update_scheme
@@ -38,15 +37,15 @@ class INE(Plugin):
         vid = self.url_re.match(self.url).group(1)
         self.logger.debug("Found video ID: {0}", vid)
 
-        page = http.get(self.play_url.format(vid=vid))
+        page = self.session.http.get(self.play_url.format(vid=vid))
         js_url_m = self.js_re.search(page.text)
         if js_url_m:
             js_url = js_url_m.group(1)
             self.logger.debug("Loading player JS: {0}", js_url)
 
-            res = http.get(js_url)
+            res = self.session.http.get(js_url)
             metadata_url = update_scheme(self.url, self.setup_schema.validate(res.text))
-            data = http.json(http.get(metadata_url))
+            data = self.session.http.json(self.session.http.get(metadata_url))
 
             for source in data["playlist"][0]["sources"]:
                 if source["type"] == "application/vnd.apple.mpegurl":
diff --git a/src/streamlink/plugins/itvplayer.py b/src/streamlink/plugins/itvplayer.py
index f8140616..9344a8ec 100644
--- a/src/streamlink/plugins/itvplayer.py
+++ b/src/streamlink/plugins/itvplayer.py
@@ -4,7 +4,7 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HLSStream
 
@@ -49,7 +49,7 @@ class ITVPlayer(Plugin):
                                         "platformTag": "dotcom"}}
 
     def video_info(self):
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         for div in itertags(page.text, 'div'):
             if div.attributes.get("id") == "video":
                 return div.attributes
@@ -59,14 +59,14 @@ class ITVPlayer(Plugin):
             Find all the streams for the ITV url
             :return: Mapping of quality to stream
         """
-        http.headers.update({"User-Agent": useragents.FIREFOX})
+        self.session.http.headers.update({"User-Agent": useragents.FIREFOX})
         video_info = self.video_info()
         video_info_url = video_info.get("data-html5-playlist") or video_info.get("data-video-id")
 
-        res = http.post(video_info_url,
+        res = self.session.http.post(video_info_url,
                         data=json.dumps(self.device_info),
                         headers={"hmac": video_info.get("data-video-hmac")})
-        data = http.json(res, schema=self._video_info_schema)
+        data = self.session.http.json(res, schema=self._video_info_schema)
 
         log.debug("Video ID info response: {0}".format(data))
 
diff --git a/src/streamlink/plugins/kanal7.py b/src/streamlink/plugins/kanal7.py
index fd22aa40..3d1e5103 100644
--- a/src/streamlink/plugins/kanal7.py
+++ b/src/streamlink/plugins/kanal7.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -19,7 +18,7 @@ class Kanal7(Plugin):
         return cls.url_re.match(url) is not None
 
     def find_iframe(self, url):
-        res = http.get(url)
+        res = self.session.http.get(url)
         # find iframe url
         iframe = self.iframe_re.search(res.text)
         iframe_url = iframe and iframe.group(1)
@@ -33,7 +32,7 @@ class Kanal7(Plugin):
         if iframe1:
             iframe2 = self.find_iframe(iframe1)
             if iframe2:
-                ires = http.get(iframe2)
+                ires = self.session.http.get(iframe2)
                 stream_m = self.stream_re.search(ires.text)
                 stream_url = stream_m and stream_m.group(1)
                 if stream_url:
diff --git a/src/streamlink/plugins/kingkong.py b/src/streamlink/plugins/kingkong.py
index e50b8144..13fce03d 100644
--- a/src/streamlink/plugins/kingkong.py
+++ b/src/streamlink/plugins/kingkong.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream, HLSStream
 
 API_URL = "https://g-api.langlive.com/webapi/v1/room/info?room_id={0}"
@@ -70,15 +70,15 @@ class Kingkong(Plugin):
         vid = match.group("vid")
 
         if vid:
-            res = http.get(VOD_API_URL.format(vid))
-            data = http.json(res, schema=_vod_schema)
+            res = self.session.http.get(VOD_API_URL.format(vid))
+            data = self.session.http.json(res, schema=_vod_schema)
             yield "source", HLSStream(
                 self.session, data["live_info"]["video"])
             return
 
         channel = match.group("channel")
-        res = http.get(API_URL.format(channel))
-        room = http.json(res, schema=_room_schema)
+        res = self.session.http.get(API_URL.format(channel))
+        room = self.session.http.json(res, schema=_room_schema)
         if not room:
             self.logger.info("Not a valid room url.")
             return
diff --git a/src/streamlink/plugins/live_russia_tv.py b/src/streamlink/plugins/live_russia_tv.py
index e8860718..b940579c 100644
--- a/src/streamlink/plugins/live_russia_tv.py
+++ b/src/streamlink/plugins/live_russia_tv.py
@@ -2,7 +2,7 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HLSStream, HTTPStream
 
@@ -18,7 +18,7 @@ class LiveRussia(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_iframe_url(self, url):
-        res = http.get(url)
+        res = self.session.http.get(url)
         for iframe in itertags(res.text, 'iframe'):
             src = iframe.attributes.get("src")
             if src:
@@ -26,7 +26,7 @@ class LiveRussia(Plugin):
 
     def _get_stream_info_url(self, url):
         data = {}
-        res = http.get(url)
+        res = self.session.http.get(url)
         for m in self._data_re.finditer(res.text):
             data[m.group(1)] = m.group(2)
 
@@ -47,8 +47,8 @@ class LiveRussia(Plugin):
 
             if info_url:
                 log.debug("Getting info from URL: {0}".format(info_url))
-                res = http.get(info_url, headers={"Referer": iframe_url})
-                data = http.json(res)
+                res = self.session.http.get(info_url, headers={"Referer": iframe_url})
+                data = self.session.http.json(res)
 
                 if data['status'] == 200:
                     for media in data['data']['playlist']['medialist']:
diff --git a/src/streamlink/plugins/liveedu.py b/src/streamlink/plugins/liveedu.py
index c21b12da..81740a3d 100644
--- a/src/streamlink/plugins/liveedu.py
+++ b/src/streamlink/plugins/liveedu.py
@@ -5,7 +5,6 @@ from streamlink.plugin import Plugin, PluginArguments, PluginArgument
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.stream import RTMPStream
-from streamlink.plugin.api import http
 from streamlink.compat import urljoin
 
 
@@ -58,12 +57,12 @@ class LiveEdu(Plugin):
         password = self.get_option("password")
 
         if email and password:
-            res = http.get(self.login_url)
+            res = self.session.http.get(self.login_url)
             csrf_match = self.csrf_re.search(res.text)
             token = csrf_match and csrf_match.group(1)
             self.logger.debug("Attempting login as {0} (token={1})", email, token)
 
-            res = http.post(self.login_url,
+            res = self.session.http.post(self.login_url,
                             data=dict(login=email, password=password, csrfmiddlewaretoken=token),
                             allow_redirects=False,
                             raise_for_status=False,
@@ -81,7 +80,7 @@ class LiveEdu(Plugin):
         # attempt a login
         self.login()
 
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         # decode the config for the page
         matches = self.config_re.finditer(res.text)
         try:
@@ -100,8 +99,8 @@ class LiveEdu(Plugin):
         else:
             return
 
-        ares = http.get(api_url)
-        data = http.json(ares, schema=self.api_schema)
+        ares = self.session.http.get(api_url)
+        data = self.session.http.json(ares, schema=self.api_schema)
         viewing_urls = data["viewing_urls"]
 
         if "error" in viewing_urls:
diff --git a/src/streamlink/plugins/liveme.py b/src/streamlink/plugins/liveme.py
index f7a83b88..2ca5ce3d 100644
--- a/src/streamlink/plugins/liveme.py
+++ b/src/streamlink/plugins/liveme.py
@@ -2,7 +2,6 @@ import random
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.compat import urlparse, parse_qsl
 from streamlink.stream import HLSStream
@@ -49,8 +48,8 @@ class LiveMe(Plugin):
                 'vali': vali
             }
             self.logger.debug("Found Video ID: {0}".format(video_id))
-            res = http.post(self.api_url, data=data)
-            data = http.json(res, schema=self.api_schema)
+            res = self.session.http.post(self.api_url, data=data)
+            data = self.session.http.json(res, schema=self.api_schema)
             hls = self._make_stream(data["video_info"]["hlsvideosource"])
             video = self._make_stream(data["video_info"]["videosource"])
             if hls:
diff --git a/src/streamlink/plugins/livestream.py b/src/streamlink/plugins/livestream.py
index d170b4dc..29ceee33 100644
--- a/src/streamlink/plugins/livestream.py
+++ b/src/streamlink/plugins/livestream.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_json
 from streamlink.stream import AkamaiHDStream, HLSStream
 
@@ -69,7 +69,7 @@ class Livestream(Plugin):
         return _url_re.match(url)
 
     def _get_stream_info(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = re.search("window.config = ({.+})", res.text)
         if match:
             config = match.group(1)
@@ -77,8 +77,8 @@ class Livestream(Plugin):
                               schema=_stream_config_schema)
 
     def _parse_smil(self, url, swf_url):
-        res = http.get(url)
-        smil = http.xml(res, "SMIL config", schema=_smil_schema)
+        res = self.session.http.get(url)
+        smil = self.session.http.xml(res, "SMIL config", schema=_smil_schema)
 
         for src, bitrate in smil["videos"]:
             url = urljoin(smil["http_base"], src)
diff --git a/src/streamlink/plugins/lrt.py b/src/streamlink/plugins/lrt.py
index 2ab41b49..e6838be0 100644
--- a/src/streamlink/plugins/lrt.py
+++ b/src/streamlink/plugins/lrt.py
@@ -3,7 +3,6 @@ import re
 from functools import partial
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 from streamlink.compat import urlparse
@@ -22,7 +21,7 @@ class LRT(Plugin):
         return cls._url_re.match(url)
 
     def _get_streams(self):
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         m = self._source_re.search(page.text)
         if m:
             params = ""
diff --git a/src/streamlink/plugins/media_ccc_de.py b/src/streamlink/plugins/media_ccc_de.py
index 1403811c..10cd7f27 100644
--- a/src/streamlink/plugins/media_ccc_de.py
+++ b/src/streamlink/plugins/media_ccc_de.py
@@ -22,7 +22,6 @@ Limitations:
 import re
 
 from streamlink.plugin import Plugin, PluginError
-from streamlink.plugin.api import http
 from streamlink.stream import HTTPStream, HLSStream
 
 API_URL_MEDIA = "https://api.media.ccc.de"
@@ -50,7 +49,7 @@ def get_event_id(url):
     :param url: talk URL
 
     """
-    match = re.search(r"{event_id:\s(?P<event_id>\d+),.*}", http.get(url).text)
+    match = re.search(r"{event_id:\s(?P<event_id>\d+),.*}", self.session.http.get(url).text)
 
     try:
         event_id = int(match.group('event_id'))
@@ -66,9 +65,9 @@ def get_json(url):
     :param url: URL to fetch
 
     """
-    res = http.get(url)
+    res = self.session.http.get(url)
 
-    return http.json(res)
+    return self.session.http.json(res)
 
 
 def parse_media_json(json_object):
diff --git a/src/streamlink/plugins/mediaklikk.py b/src/streamlink/plugins/mediaklikk.py
index 0da06e7f..3f91dd73 100644
--- a/src/streamlink/plugins/mediaklikk.py
+++ b/src/streamlink/plugins/mediaklikk.py
@@ -2,7 +2,6 @@ import re
 
 from streamlink.plugin import Plugin
 from streamlink.stream import HLSStream
-from streamlink.plugin.api import http
 
 
 _stream_url_re = re.compile(r"http(s)?://(www\.)?mediaklikk.hu/([A-Za-z0-9\-]+)/?")
@@ -19,14 +18,14 @@ class Mediaklikk(Plugin):
 
     def _get_playlist_url(self):
         # get the id
-        content = http.get(self.url)
+        content = self.session.http.get(self.url)
         match = _id_re.match(content.text.replace("\n", ""))
         if not match:
             return
 
         # get the m3u8 file url
         player_url = _stream_player_url.format(match.group(1))
-        content = http.get(player_url)
+        content = self.session.http.get(player_url)
 
         match = _file_re.match(content.text.replace("\n", ""))
         if match:
diff --git a/src/streamlink/plugins/mips.py b/src/streamlink/plugins/mips.py
index b03079c6..06a3ac63 100644
--- a/src/streamlink/plugins/mips.py
+++ b/src/streamlink/plugins/mips.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_query
 from streamlink.stream import RTMPStream
 
@@ -44,12 +44,12 @@ class Mips(Plugin):
 
         headers = {"Referer": self.url}
         url = PLAYER_URL.format(channel)
-        res = http.get(url, headers=headers, schema=_schema)
+        res = self.session.http.get(url, headers=headers, schema=_schema)
         if not res or "s" not in res:
             return
 
         streams = {}
-        server = http.get(BALANCER_URL, headers=headers, schema=_rtmp_schema)
+        server = self.session.http.get(BALANCER_URL, headers=headers, schema=_rtmp_schema)
         playpath = "{0}?{1}".format(res["s"], res["id"])
         streams["live"] = RTMPStream(self.session, {
             "rtmp": "rtmp://{0}/live/{1}".format(server, playpath),
diff --git a/src/streamlink/plugins/mitele.py b/src/streamlink/plugins/mitele.py
index 8d0bd47d..5be5fa10 100644
--- a/src/streamlink/plugins/mitele.py
+++ b/src/streamlink/plugins/mitele.py
@@ -5,7 +5,6 @@ import re
 from streamlink import NoStreamsError
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -65,7 +64,7 @@ class Mitele(Plugin):
         :param channel: channel name
         :return: "gcp" and "ogn"
         """
-        res = http.get(self.pdata_url.format(channel=channel))
+        res = self.session.http.get(self.pdata_url.format(channel=channel))
         return parse_json(res.text, schema=self.pdata_schema)
 
     def create_hls_url(self, suffix):
@@ -95,7 +94,7 @@ class Mitele(Plugin):
         :return: hls_url
         """
         try:
-            res = http.post(self.gate_url, headers=self.headers, data=data)
+            res = self.session.http.post(self.gate_url, headers=self.headers, data=data)
         except Exception as e:
             if "403" in str(e):
                 self.logger.error("This Video is Not Available in Your Country.")
diff --git a/src/streamlink/plugins/mixer.py b/src/streamlink/plugins/mixer.py
index 34b0ead8..95565f7f 100644
--- a/src/streamlink/plugins/mixer.py
+++ b/src/streamlink/plugins/mixer.py
@@ -7,7 +7,7 @@ import re
 from streamlink import NoStreamsError
 from streamlink.compat import urlparse, parse_qsl, urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 _url_re = re.compile(r"http(s)?://(\w+.)?mixer\.com/(?P<channel>[^/?]+)")
@@ -41,7 +41,7 @@ class Mixer(Plugin):
 
     def _get_api_res(self, api_type, api_id):
         try:
-            res = http.get(self.api_url.format(type=api_type, id=api_id))
+            res = self.session.http.get(self.api_url.format(type=api_type, id=api_id))
             return res
         except Exception as e:
             if "404" in str(e):
@@ -53,7 +53,7 @@ class Mixer(Plugin):
     def _get_vod_stream(self, vod_id):
         res = self._get_api_res("recordings", vod_id)
 
-        for sdata in http.json(res, schema=self._vod_schema):
+        for sdata in self.session.http.json(res, schema=self._vod_schema):
             if sdata["format"] == "hls":
                 hls_url = urljoin(sdata["url"], "manifest.m3u8")
                 yield "{0}p".format(sdata["height"]), HLSStream(self.session, hls_url)
@@ -61,7 +61,7 @@ class Mixer(Plugin):
     def _get_live_stream(self, channel):
         res = self._get_api_res("channels", channel)
 
-        channel_info = http.json(res)
+        channel_info = self.session.http.json(res)
         if not channel_info["online"]:
             return
 
diff --git a/src/streamlink/plugins/mlgtv.py b/src/streamlink/plugins/mlgtv.py
index 6c5b966f..00bbe5a0 100644
--- a/src/streamlink/plugins/mlgtv.py
+++ b/src/streamlink/plugins/mlgtv.py
@@ -2,7 +2,6 @@ import re
 
 from streamlink.exceptions import NoStreamsError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_json
 from streamlink.stream import HDSStream
@@ -62,8 +61,8 @@ class MLGTV(Plugin):
             if r_json:
                 mlg_channel_id = r_json.get("mlg_channel_id")
                 if mlg_channel_id:
-                    res = http.get(self.CHANNEL_API.format(mlg_channel_id))
-                    channel_id = http.json(res, schema=self._site_data_schema)
+                    res = self.session.http.get(self.CHANNEL_API.format(mlg_channel_id))
+                    channel_id = self.session.http.json(res, schema=self._site_data_schema)
                     return channel_id
 
         match = self._player_embed_re.search(text)
@@ -83,7 +82,7 @@ class MLGTV(Plugin):
             channel_id = match.group("channel_id")
         else:
             try:
-                res = http.get(self.url)
+                res = self.session.http.get(self.url)
             except Exception as e:
                 raise NoStreamsError(self.url)
             channel_id = self._find_channel_id(res.text)
@@ -92,7 +91,7 @@ class MLGTV(Plugin):
             return
         self.logger.info("Channel ID: {0}".format(channel_id))
 
-        res = http.get(self.PLAYER_EMBED_URL.format(channel_id))
+        res = self.session.http.get(self.PLAYER_EMBED_URL.format(channel_id))
         items = self._find_stream_id(res.text)
         if not items:
             return
diff --git a/src/streamlink/plugins/nbc.py b/src/streamlink/plugins/nbc.py
index defa227e..68019319 100644
--- a/src/streamlink/plugins/nbc.py
+++ b/src/streamlink/plugins/nbc.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugins.theplatform import ThePlatform
 from streamlink.utils import update_scheme
 
@@ -15,7 +14,7 @@ class NBC(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.embed_url_re.search(res.text)
         platform_url = m and m.group("url")
 
diff --git a/src/streamlink/plugins/nbcsports.py b/src/streamlink/plugins/nbcsports.py
index ed23533b..2b81a7da 100644
--- a/src/streamlink/plugins/nbcsports.py
+++ b/src/streamlink/plugins/nbcsports.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugins.theplatform import ThePlatform
 from streamlink.utils import update_scheme
 
@@ -15,7 +14,7 @@ class NBCSports(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.embed_url_re.search(res.text)
         platform_url = m and m.group("url")
 
diff --git a/src/streamlink/plugins/nhkworld.py b/src/streamlink/plugins/nhkworld.py
index 1239a25f..8215798f 100644
--- a/src/streamlink/plugins/nhkworld.py
+++ b/src/streamlink/plugins/nhkworld.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 API_URL = "http://{}.nhk.or.jp/nhkworld/app/tv/hlslive_web.xml"
@@ -22,9 +22,9 @@ class NHKWorld(Plugin):
     def _get_streams(self):
         # get the HLS xml from the same sub domain as the main url, defaulting to www
         sdomain = _url_re.match(self.url).group(1) or "www"
-        res = http.get(API_URL.format(sdomain))
+        res = self.session.http.get(API_URL.format(sdomain))
 
-        stream_url = http.xml(res, schema=_schema)
+        stream_url = self.session.http.xml(res, schema=_schema)
         return HLSStream.parse_variant_playlist(self.session, stream_url)
 
 
diff --git a/src/streamlink/plugins/nos.py b/src/streamlink/plugins/nos.py
index 66ee1b68..439e6d26 100644
--- a/src/streamlink/plugins/nos.py
+++ b/src/streamlink/plugins/nos.py
@@ -10,7 +10,6 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HLSStream
 
@@ -25,20 +24,20 @@ class NOS(Plugin):
         return cls._url_re.match(url)
 
     def _resolve_stream(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         for video in itertags(res.text, 'video'):
             stream_url = video.attributes.get("data-stream")
             log.debug("Stream data: {0}".format(stream_url))
             return HLSStream.parse_variant_playlist(self.session, stream_url)
 
     def _get_source_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         for atag in itertags(res.text, 'a'):
             if "video-play__link" in atag.attributes.get("class", ""):
                 href = urljoin(self.url, atag.attributes.get("href"))
                 log.debug("Loading embedded video page")
-                vpage = http.get(href, params=dict(ajax="true", npo_cc_skip_wall="true"))
+                vpage = self.session.http.get(href, params=dict(ajax="true", npo_cc_skip_wall="true"))
                 for source in itertags(vpage.text, 'source'):
                     return HLSStream.parse_variant_playlist(self.session, source.attributes.get("src"))
 
diff --git a/src/streamlink/plugins/npo.py b/src/streamlink/plugins/npo.py
index fae4b55a..7c63c44c 100644
--- a/src/streamlink/plugins/npo.py
+++ b/src/streamlink/plugins/npo.py
@@ -13,7 +13,6 @@ Supports:
 import re
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -61,12 +60,12 @@ class NPO(Plugin):
     def __init__(self, url):
         super(NPO, self).__init__(url)
         self._token = None
-        http.headers.update({"User-Agent": useragents.CHROME})
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
 
     def api_call(self, endpoint, schema=None, params=None):
         url = self.api_url.format(endpoint=endpoint)
-        res = http.get(url, params=params)
-        return http.json(res, schema=schema)
+        res = self.session.http.get(url, params=params)
+        return self.session.http.json(res, schema=schema)
 
     @property
     def token(self):
@@ -75,7 +74,7 @@ class NPO(Plugin):
         return self._token
 
     def _get_prid(self, subtitles=False):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         bprid = None
 
         # Locate the asset id for the content on the page
@@ -117,7 +116,7 @@ class NPO(Plugin):
                         info_url = stream["url"].replace("type=jsonp", "type=json")
 
                         # find the actual stream URL
-                        stream_url = http.json(http.get(info_url),
+                        stream_url = self.session.http.json(self.session.http.get(info_url),
                                                schema=self.stream_info_schema)
 
                     if stream["format"] in ("adaptive", "hls"):
diff --git a/src/streamlink/plugins/nrk.py b/src/streamlink/plugins/nrk.py
index 031c4cb9..107ee017 100644
--- a/src/streamlink/plugins/nrk.py
+++ b/src/streamlink/plugins/nrk.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 COOKIE_PARAMS = (
@@ -49,13 +49,13 @@ class NRK(Plugin):
         }
 
         # Construct API URL for this program.
-        baseurl = http.get(self.url, cookies=cookie, schema=_schema)
+        baseurl = self.session.http.get(self.url, cookies=cookie, schema=_schema)
         program_id = _id_re.search(self.url).group(1)
 
         # Extract media URL.
         json_url = urljoin(baseurl, "mediaelement/{0}".format(program_id))
-        res = http.get(json_url, cookies=cookie)
-        media_element = http.json(res, schema=_mediaelement_schema)
+        res = self.session.http.get(json_url, cookies=cookie)
+        media_element = self.session.http.json(res, schema=_mediaelement_schema)
         media_url = media_element["mediaUrl"]
 
         return HLSStream.parse_variant_playlist(self.session, media_url)
diff --git a/src/streamlink/plugins/ok_live.py b/src/streamlink/plugins/ok_live.py
index cdec286c..233c510c 100644
--- a/src/streamlink/plugins/ok_live.py
+++ b/src/streamlink/plugins/ok_live.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
@@ -33,7 +33,7 @@ class OK_live(Plugin):
             'Referer': self.url
         }
 
-        hls  = http.get(self.url, headers=headers, schema=_schema)
+        hls  = self.session.http.get(self.url, headers=headers, schema=_schema)
         if hls:
             hls = hls.replace(u'\\\\u0026', u'&')
         return HLSStream.parse_variant_playlist(self.session, hls, headers=headers)
diff --git a/src/streamlink/plugins/olympicchannel.py b/src/streamlink/plugins/olympicchannel.py
index 3b59b21c..15af15e7 100644
--- a/src/streamlink/plugins/olympicchannel.py
+++ b/src/streamlink/plugins/olympicchannel.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream
 
@@ -21,10 +20,10 @@ class OlympicChannel(Plugin):
         return cls._url_re.match(url)
 
     def _get_vod_streams(self):
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         asset = re.search(r'asse_.{32}', str(page._content)).group(0)
         post_data = '{"asset_url":"/api/assets/%s/"}' % asset
-        stream_data = http.json(http.post(self._stream_get_url, data=post_data))['objects'][0]['level3']['streaming_url']
+        stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['objects'][0]['level3']['streaming_url']
         return HLSStream.parse_variant_playlist(self.session, stream_data)
 
     def _get_live_streams(self, lang, path):
@@ -34,13 +33,13 @@ class OlympicChannel(Plugin):
         :param path:
         :return:
         """
-        res = http.get(self._live_api_url.format(lang, path))
-        live_res = http.json(res)['default']['uid']
+        res = self.session.http.get(self._live_api_url.format(lang, path))
+        live_res = self.session.http.json(res)['default']['uid']
         post_data = '{"channel_url":"/api/channels/%s/"}' % live_res
         try:
-            stream_data = http.json(http.post(self._stream_get_url, data=post_data))['stream_url']
+            stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['stream_url']
         except BaseException:
-            stream_data = http.json(http.post(self._stream_get_url, data=post_data))['channel_url']
+            stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['channel_url']
         return HLSStream.parse_variant_playlist(self.session, stream_data)
 
     def _get_streams(self):
diff --git a/src/streamlink/plugins/onetv.py b/src/streamlink/plugins/onetv.py
index 35b482bd..81553a01 100644
--- a/src/streamlink/plugins/onetv.py
+++ b/src/streamlink/plugins/onetv.py
@@ -3,7 +3,6 @@ import re
 
 from streamlink.compat import urlencode, unquote, urljoin
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.plugin import stream_weight
 from streamlink.stream import HLSStream, HTTPStream, DASHStream
 from streamlink.utils import update_scheme
@@ -46,8 +45,8 @@ class OneTV(Plugin):
         return update_scheme(self.url, url)
 
     def hls_session(self):
-        res = http.get(update_scheme(self.url, self._session_api))
-        data = http.json(res)
+        res = self.session.http.get(update_scheme(self.url, self._session_api))
+        data = self.session.http.json(res)
         # the values are already quoted, we don't want them quoted
         return dict((k, unquote(v)) for k, v in data.items())
 
@@ -61,20 +60,20 @@ class OneTV(Plugin):
         Get the VOD data path and the default VOD ID
         :return:
         """
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         m = self._vod_re.search(page.text)
         vod_data_url = m and urljoin(self.url, m.group(0))
         if vod_data_url:
             self.logger.debug("Found VOD data url: {0}", vod_data_url)
-            res = http.get(vod_data_url)
-            return http.json(res)
+            res = self.session.http.get(vod_data_url)
+            return self.session.http.json(res)
 
     def _get_streams(self):
         if self.is_live:
             self.logger.debug("Loading live stream for {0}...", self.channel)
 
-            res = http.get(self.live_api_url, data={"r": random.randint(1, 100000)})
-            live_data = http.json(res)
+            res = self.session.http.get(self.live_api_url, data={"r": random.randint(1, 100000)})
+            live_data = self.session.http.json(res)
 
             # all the streams are equal for each type, so pick a random one
             hls_streams = live_data.get("hls")
diff --git a/src/streamlink/plugins/openrectv.py b/src/streamlink/plugins/openrectv.py
index ecebc230..6f300691 100644
--- a/src/streamlink/plugins/openrectv.py
+++ b/src/streamlink/plugins/openrectv.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -46,13 +46,13 @@ class OPENRECtv(Plugin):
         stype = _url_re.match(self.url).group(1)
         if stype.lower() == "live":
             self.logger.debug("Searching the page for live stream URLs")
-            playlists = http.get(self.url, schema=_live_schema)
+            playlists = self.session.http.get(self.url, schema=_live_schema)
             for playlist in playlists:
                 for q, s in HLSStream.parse_variant_playlist(self.session, playlist["url"]).items():
                     yield "source" if playlist["isSource"] else q, s
         elif stype.lower() == "movie":
             self.logger.debug("Searching the page for VOD stream URLs")
-            playlist = http.get(self.url, schema=_movie_schema)
+            playlist = self.session.http.get(self.url, schema=_movie_schema)
             if playlist:
                 for s in HLSStream.parse_variant_playlist(self.session, playlist).items():
                     yield s
diff --git a/src/streamlink/plugins/orf_tvthek.py b/src/streamlink/plugins/orf_tvthek.py
index 53d5b5e9..5015b6e1 100644
--- a/src/streamlink/plugins/orf_tvthek.py
+++ b/src/streamlink/plugins/orf_tvthek.py
@@ -2,7 +2,6 @@ import re
 import json
 
 from streamlink.plugin import Plugin, PluginError
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 _stream_url_re = re.compile(r'https?://tvthek\.orf\.at/(index\.php/)?live/(?P<title>[^/]+)/(?P<id>[0-9]+)')
@@ -23,7 +22,7 @@ class ORFTVThek(Plugin):
         else:
             mode = MODE_VOD
 
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _json_re.search(res.text)
         if match:
             data = json.loads(_json_re.search(res.text).group('json').replace('&quot;', '"'))
@@ -48,7 +47,7 @@ class ORFTVThek(Plugin):
                 continue
             stream = HLSStream.parse_variant_playlist(self.session, url)
             # work around broken HTTP connection persistence by acquiring a new connection
-            http.close()
+            self.session.http.close()
             streams.update(stream)
 
         return streams
diff --git a/src/streamlink/plugins/ovvatv.py b/src/streamlink/plugins/ovvatv.py
index 42a40f00..fcf7e842 100644
--- a/src/streamlink/plugins/ovvatv.py
+++ b/src/streamlink/plugins/ovvatv.py
@@ -6,7 +6,6 @@ from pprint import pprint
 
 from streamlink import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -41,18 +40,18 @@ class ovvaTV(Plugin):
 
     @Plugin.broken()
     def _get_streams(self):
-        http.headers = {"User-Agent": useragents.ANDROID}
-        res = http.get(self.url)
+        self.session.http.headers = {"User-Agent": useragents.ANDROID}
+        res = self.session.http.get(self.url)
         iframe_url = self.find_iframe(res)
 
         if iframe_url:
             self.logger.debug("Found iframe: {0}", iframe_url)
-            res = http.get(iframe_url, headers={"Referer": self.url})
+            res = self.session.http.get(iframe_url, headers={"Referer": self.url})
             data = self.data_re.search(res.text)
             if data:
                 try:
                     ovva_url = parse_json(b64decode(data.group(1)).decode("utf8"), schema=self.ovva_data_schema)
-                    stream_url = http.get(ovva_url, schema=self.ovva_redirect_schema)
+                    stream_url = self.session.http.get(ovva_url, schema=self.ovva_redirect_schema)
                 except PluginError as e:
                     self.logger.error("Could not find stream URL: {0}", e)
                 else:
diff --git a/src/streamlink/plugins/pandatv.py b/src/streamlink/plugins/pandatv.py
index 56d7ab2a..a73db24c 100644
--- a/src/streamlink/plugins/pandatv.py
+++ b/src/streamlink/plugins/pandatv.py
@@ -5,7 +5,7 @@ import json
 
 from streamlink.compat import quote
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream, HLSStream
 
 ROOM_API = "https://www.panda.tv/api_room_v3?token=&hostid={0}&roomid={1}&roomkey={2}&_={3}&param={4}&time={5}&sign={6}"
@@ -67,7 +67,7 @@ class Pandatv(Plugin):
         prefix = match.group("prefix")
         channel = match.group("channel")
 
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         if prefix == 'xingyan.':
             roominfo = _roominfo_re.search(res.text).group(1)
@@ -93,7 +93,7 @@ class Pandatv(Plugin):
 
         ts = int(time.time())
         url = ROOM_API_V2.format(channel, ts)
-        res = http.get(url)
+        res = self.session.http.get(url)
 
         try:
             status = _status_re.search(res.text).group(1)
@@ -117,8 +117,8 @@ class Pandatv(Plugin):
         param = param.replace("\\", "")
         param = quote(param)
         url = ROOM_API.format(hostid, channel, room_key, ts, param, tt, sign)
-        room = http.get(url)
-        data = http.json(room, schema=_room_schema)
+        room = self.session.http.get(url)
+        data = self.session.http.json(room, schema=_room_schema)
         if not isinstance(data, dict):
             self.logger.info("Please Check PandaTV Room API")
             return
diff --git a/src/streamlink/plugins/periscope.py b/src/streamlink/plugins/periscope.py
index 753980ef..ee10e753 100644
--- a/src/streamlink/plugins/periscope.py
+++ b/src/streamlink/plugins/periscope.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.exceptions import NoStreamsError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 STREAM_INFO_URL = "https://api.periscope.tv/api/v2/getAccessPublic"
@@ -37,14 +37,14 @@ class Periscope(Plugin):
 
     def _get_streams(self):
         match = _url_re.match(self.url)
-        res = http.get(STREAM_INFO_URL,
+        res = self.session.http.get(STREAM_INFO_URL,
                        params=match.groupdict(),
                        acceptable_status=STATUS_UNAVAILABLE)
 
         if res.status_code in STATUS_UNAVAILABLE:
             return
 
-        data = http.json(res, schema=_stream_schema)
+        data = self.session.http.json(res, schema=_stream_schema)
         if data.get("hls_url"):
             hls_url = data["hls_url"]
             hls_name = "live"
diff --git a/src/streamlink/plugins/picarto.py b/src/streamlink/plugins/picarto.py
index 4cde64aa..026a62be 100644
--- a/src/streamlink/plugins/picarto.py
+++ b/src/streamlink/plugins/picarto.py
@@ -4,9 +4,10 @@ import re
 import json
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.stream import RTMPStream
+from streamlink.utils import parse_json
 
 
 class Picarto(Plugin):
@@ -16,13 +17,29 @@ class Picarto(Plugin):
     RTMP_PLAYPATH = "golive+{channel}?token={token}"
     HLS_URL = "https://{server}/hls/{channel}/index.m3u8?token={token}"
 
+
     # Regex for all usable URLs
     _url_re = re.compile(r"""
         https?://(?:\w+\.)?picarto\.tv/(?:videopopout/)?([^&?/]+)
     """, re.VERBOSE)
 
     # Regex for VOD extraction
-    _vod_re = re.compile(r'''vod: "(https?://[\S]+?/index.m3u8)",''')
+    _vod_re = re.compile(r'''(?<=#vod-player", )(\{.*?\})''')
+
+    data_schema = validate.Schema(
+        validate.transform(_vod_re.search),
+        validate.any(
+            None,
+            validate.all(
+                validate.get(0),
+                validate.transform(parse_json),
+                {
+                    "vod": validate.url(),
+                }
+            )
+        )
+    )
+
 
     @classmethod
     def can_handle_url(cls, url):
@@ -53,9 +70,10 @@ class Picarto(Plugin):
         return RTMPStream(self.session, params=params)
 
     def _get_vod_stream(self, page):
-        m = self._vod_re.search(page.text)
-        if m:
-            return HLSStream.parse_variant_playlist(self.session, m.group(1))
+        data = self.data_schema.validate(page.text)
+
+        if data:
+            return HLSStream.parse_variant_playlist(self.session, data["vod"])
 
     def _get_streams(self):
         url_channel_name = self._url_re.match(self.url).group(1)
@@ -63,7 +81,7 @@ class Picarto(Plugin):
         # Handle VODs first, since their "channel name" is different
         if url_channel_name.endswith(".flv"):
             self.logger.debug("Possible VOD stream...")
-            page = http.get(self.url)
+            page = self.session.http.get(self.url)
             vod_streams = self._get_vod_stream(page)
             if vod_streams:
                 for s in vod_streams.items():
@@ -72,7 +90,7 @@ class Picarto(Plugin):
             else:
                 self.logger.warning("Probably a VOD stream but no VOD found?")
 
-        ci = http.get(self.CHANNEL_API_URL.format(channel=url_channel_name), raise_for_status=False)
+        ci = self.session.http.get(self.CHANNEL_API_URL.format(channel=url_channel_name), raise_for_status=False)
 
         if ci.status_code == 404:
             self.logger.error("The channel {0} does not exist".format(url_channel_name))
@@ -89,7 +107,7 @@ class Picarto(Plugin):
         channel = channel_api_json["name"]
 
         # Extract preferred edge server and available techs from the undocumented channel API
-        channel_server_res = http.post(self.VIDEO_API_URL, data={"loadbalancinginfo": channel})
+        channel_server_res = self.session.http.post(self.VIDEO_API_URL, data={"loadbalancinginfo": channel})
         info_json = json.loads(channel_server_res.text)
         pref = info_json["preferedEdge"]
         for i in info_json["edges"]:
diff --git a/src/streamlink/plugins/piczel.py b/src/streamlink/plugins/piczel.py
index e6bac79b..1fdaa5b9 100644
--- a/src/streamlink/plugins/piczel.py
+++ b/src/streamlink/plugins/piczel.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream, HLSStream
 
 STREAMS_URL = "https://piczel.tv:3000/streams/{0}?&page=1&sfw=false&live_only=true"
@@ -36,8 +36,8 @@ class Piczel(Plugin):
 
         channel_name = match.group(1)
 
-        res = http.get(STREAMS_URL.format(channel_name))
-        streams = http.json(res, schema=_streams_schema)
+        res = self.session.http.get(STREAMS_URL.format(channel_name))
+        streams = self.session.http.json(res, schema=_streams_schema)
         if streams["type"] not in ("multi", "stream"):
             return
 
diff --git a/src/streamlink/plugins/pixiv.py b/src/streamlink/plugins/pixiv.py
index e20ad9a9..005c83e8 100644
--- a/src/streamlink/plugins/pixiv.py
+++ b/src/streamlink/plugins/pixiv.py
@@ -6,7 +6,6 @@ from streamlink.compat import urljoin
 from streamlink.exceptions import NoStreamsError
 from streamlink.plugin import Plugin
 from streamlink.plugin import PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -67,7 +66,7 @@ class Pixiv(Plugin):
 
     def find_videopage(self):
         self.logger.debug("Not a videopage")
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         m = self._videopage_re.search(res.text)
         if not m:
@@ -79,7 +78,7 @@ class Pixiv(Plugin):
         return urljoin(self.url, path)
 
     def _login(self, username, password):
-        res = http.get(self.login_url_get)
+        res = self.session.http.get(self.login_url_get)
         m = self._post_key_re.search(res.text)
         if not m:
             raise PluginError("Missing post_key, no login posible.")
@@ -93,8 +92,8 @@ class Pixiv(Plugin):
             "password": password,
         }
 
-        res = http.post(self.login_url_post, data=data)
-        res = http.json(res)
+        res = self.session.http.post(self.login_url_post, data=data)
+        res = self.session.http.json(res)
 
         if res["body"].get("success"):
             return True
@@ -102,7 +101,7 @@ class Pixiv(Plugin):
             return False
 
     def _get_streams(self):
-        http.headers = {"User-Agent": useragents.FIREFOX}
+        self.session.http.headers = {"User-Agent": useragents.FIREFOX}
 
         login_username = self.get_option("username")
         login_password = self.get_option("password")
@@ -117,7 +116,7 @@ class Pixiv(Plugin):
         if not videopage:
             self.url = self.find_videopage()
 
-        data = http.get(self.url, schema=self._data_schema)
+        data = self.session.http.get(self.url, schema=self._data_schema)
 
         if not data.get("LiveStore"):
             self.logger.debug("No video url found, stream might be offline.")
diff --git a/src/streamlink/plugins/playtv.py b/src/streamlink/plugins/playtv.py
index 9a1a8ee2..4d6056a5 100644
--- a/src/streamlink/plugins/playtv.py
+++ b/src/streamlink/plugins/playtv.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream
 
 
@@ -39,8 +39,8 @@ class PlayTV(Plugin):
         match = self._url_re.match(self.url)
         channel = match.group('channel')
 
-        res = http.get(self.FORMATS_URL.format(channel))
-        streams = http.json(res, schema=self._formats_schema)['streams']
+        res = self.session.http.get(self.FORMATS_URL.format(channel))
+        streams = self.session.http.json(res, schema=self._formats_schema)['streams']
         if streams == []:
             self.logger.error('Channel may be geo-restricted, not directly provided by PlayTV or not freely available')
             return
@@ -56,8 +56,8 @@ class PlayTV(Plugin):
                     if bitrate['value'] == 0:
                         continue
                     api_url = self.API_URL.format(channel, protocol, language, bitrate['value'])
-                    res = http.get(api_url)
-                    video_url = http.json(res, schema=self._api_schema)['url']
+                    res = self.session.http.get(api_url)
+                    video_url = self.session.http.json(res, schema=self._api_schema)['url']
                     bs = '{0}k'.format(bitrate['value'])
 
                     if protocol == 'hls':
diff --git a/src/streamlink/plugins/pluzz.py b/src/streamlink/plugins/pluzz.py
index e54727cb..3e00b4eb 100644
--- a/src/streamlink/plugins/pluzz.py
+++ b/src/streamlink/plugins/pluzz.py
@@ -3,7 +3,7 @@ import sys
 import time
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import DASHStream, HDSStream, HLSStream, HTTPStream
 from streamlink.stream.ffmpegmux import MuxedStream
 from streamlink.utils import update_scheme
@@ -97,12 +97,12 @@ class Pluzz(Plugin):
 
     def _get_streams(self):
         # Retrieve geolocation data
-        res = http.get(self.GEO_URL)
-        geo = http.json(res, schema=self._geo_schema)
+        res = self.session.http.get(self.GEO_URL)
+        geo = self.session.http.json(res, schema=self._geo_schema)
         country_code = geo['reponse']['geo_info']['country_code']
 
         # Retrieve URL page and search for video ID
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         if 'france.tv' in self.url:
             match = self._pluzz_video_id_re.search(res.text)
         elif 'ludo.fr' in self.url or 'zouzous.fr' in self.url:
@@ -117,15 +117,15 @@ class Pluzz(Plugin):
 
         # Retrieve SWF player URL
         swf_url = None
-        res = http.get(self.PLAYER_GENERATOR_URL)
-        player_url = update_scheme(self.url, http.json(res, schema=self._player_schema)['result'])
-        res = http.get(player_url)
+        res = self.session.http.get(self.PLAYER_GENERATOR_URL)
+        player_url = update_scheme(self.url, self.session.http.json(res, schema=self._player_schema)['result'])
+        res = self.session.http.get(player_url)
         match = self._swf_re.search(res.text)
         if match is not None:
             swf_url = 'https://staticftv-a.akamaihd.net/player/' + match.group(1)
 
-        res = http.get(self.API_URL.format(video_id))
-        videos = http.json(res, schema=self._api_schema)
+        res = self.session.http.get(self.API_URL.format(video_id))
+        videos = self.session.http.json(res, schema=self._api_schema)
         now = time.time()
 
         offline = False
@@ -166,12 +166,12 @@ class Pluzz(Plugin):
                 '.mpd' in video_url or
                 'france.tv' in self.url or
                 'sport.francetvinfo.fr' in self.url):
-                res = http.get(self.TOKEN_URL.format(video_url))
+                res = self.session.http.get(self.TOKEN_URL.format(video_url))
                 video_url = res.text
 
             if '.mpd' in video_url:
                 # Get redirect video URL
-                res = http.get(res.text)
+                res = self.session.http.get(res.text)
                 video_url = res.url
                 for bitrate, stream in DASHStream.parse_manifest(self.session,
                                                                  video_url).items():
diff --git a/src/streamlink/plugins/powerapp.py b/src/streamlink/plugins/powerapp.py
index 832bb5ef..0ad0dda1 100644
--- a/src/streamlink/plugins/powerapp.py
+++ b/src/streamlink/plugins/powerapp.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -24,8 +23,8 @@ class PowerApp(Plugin):
     def _get_streams(self):
         channel = self.url_re.match(self.url).group(1)
 
-        res = http.get(self.api_url.format(channel))
-        data = http.json(res, schema=self.api_schema)
+        res = self.session.http.get(self.api_url.format(channel))
+        data = self.session.http.json(res, schema=self.api_schema)
 
         return HLSStream.parse_variant_playlist(self.session, data["channel_stream_url"])
 
diff --git a/src/streamlink/plugins/qq.py b/src/streamlink/plugins/qq.py
index ff291b84..18fa1e3c 100644
--- a/src/streamlink/plugins/qq.py
+++ b/src/streamlink/plugins/qq.py
@@ -3,7 +3,6 @@ import re
 
 from streamlink.exceptions import NoStreamsError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_json
 from streamlink.stream import HLSStream
@@ -37,7 +36,7 @@ class QQ(Plugin):
             return
 
         room_id = match.group("room_id")
-        res = http.get(self.api_url.format(room_id))
+        res = self.session.http.get(self.api_url.format(room_id))
 
         data = self._data_re.search(res.text)
         if not data:
diff --git a/src/streamlink/plugins/radionet.py b/src/streamlink/plugins/radionet.py
index 7fe91937..2e542d69 100644
--- a/src/streamlink/plugins/radionet.py
+++ b/src/streamlink/plugins/radionet.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream
 from streamlink.utils import parse_json
@@ -34,7 +33,7 @@ class RadioNet(Plugin):
         return cls._url_re.match(url)
 
     def _get_streams(self):
-        streams = http.get(self.url, schema=self._stream_schema)
+        streams = self.session.http.get(self.url, schema=self._stream_schema)
         if streams is None:
             return
 
diff --git a/src/streamlink/plugins/raiplay.py b/src/streamlink/plugins/raiplay.py
index 3175726d..52f76295 100644
--- a/src/streamlink/plugins/raiplay.py
+++ b/src/streamlink/plugins/raiplay.py
@@ -2,7 +2,7 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -27,7 +27,7 @@ class RaiPlay(Plugin):
     def _get_streams(self):
         channel = self.url_re.match(self.url).group(1)
         self.logger.debug("Found channel: {0}", channel)
-        stream_url = http.get(self.url, schema=self.stream_schema)
+        stream_url = self.session.http.get(self.url, schema=self.stream_schema)
         if stream_url:
             return HLSStream.parse_variant_playlist(self.session, stream_url, headers={"User-Agent": useragents.CHROME})
 
diff --git a/src/streamlink/plugins/reshet.py b/src/streamlink/plugins/reshet.py
index 0b5e4de8..1580ecfa 100644
--- a/src/streamlink/plugins/reshet.py
+++ b/src/streamlink/plugins/reshet.py
@@ -3,7 +3,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugins.brightcove import BrightcovePlayer
 
 
@@ -24,7 +23,7 @@ class Reshet(Plugin):
         if base == "live":
             return bp.get_streams(self.live_channel_id)
         else:
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
             m = self.video_id_re.search(res.text)
             video_id = m and m.group(1)
             if video_id:
diff --git a/src/streamlink/plugins/rtbf.py b/src/streamlink/plugins/rtbf.py
index 513ce60a..544a16f6 100644
--- a/src/streamlink/plugins/rtbf.py
+++ b/src/streamlink/plugins/rtbf.py
@@ -2,7 +2,7 @@ import datetime
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import DASHStream, HLSStream, HTTPStream
 from streamlink.utils import parse_json
 from streamlink.compat import html_unescape
@@ -72,14 +72,14 @@ class RTBF(Plugin):
         if geoloc_flag == 'open':
             return True
 
-        res = http.get(cls.GEO_URL)
-        data = http.json(res, schema=cls._geo_schema)
+        res = self.session.http.get(cls.GEO_URL)
+        data = self.session.http.json(res, schema=cls._geo_schema)
         return data['country'] == geoloc_flag or data['zone'] == geoloc_flag
 
     @classmethod
     def tokenize_stream(cls, url):
-        res = http.post(cls.TOKEN_URL, data={'streams[url]': url})
-        data = http.json(res)
+        res = self.session.http.post(cls.TOKEN_URL, data={'streams[url]': url})
+        data = self.session.http.json(res)
         return data['streams']['url']
 
     @staticmethod
@@ -93,13 +93,13 @@ class RTBF(Plugin):
         return RTBF._url_re.match(url)
 
     def _get_radio_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._radio_id_re.search(res.text)
         if match is None:
             return
         radio_id = match.group('radio_id')
-        res = http.get(self.RADIO_STREAM_URL.format(radio_id))
-        streams = http.json(res, schema=self._radio_stream_schema)
+        res = self.session.http.get(self.RADIO_STREAM_URL.format(radio_id))
+        streams = self.session.http.json(res, schema=self._radio_stream_schema)
 
         for stream in streams['audioUrls']:
             match = self._stream_size_re.match(stream['url'])
@@ -110,12 +110,12 @@ class RTBF(Plugin):
             yield quality, HTTPStream(self.session, stream['url'])
 
     def _get_video_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._video_player_re.search(res.text)
         if match is None:
             return
         player_url = match.group('player_url')
-        stream_data = http.get(player_url, schema=self._video_stream_schema)
+        stream_data = self.session.http.get(player_url, schema=self._video_stream_schema)
         if stream_data is None:
             return
 
diff --git a/src/streamlink/plugins/rte.py b/src/streamlink/plugins/rte.py
index ec5fd13a..ab0111e1 100644
--- a/src/streamlink/plugins/rte.py
+++ b/src/streamlink/plugins/rte.py
@@ -2,7 +2,7 @@ from datetime import datetime
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream
 
 
@@ -72,8 +72,8 @@ class RTE(Plugin):
 
         if video_id is not None:
             # VOD
-            res = http.get(self.VOD_API_URL.format(video_id))
-            stream_data = http.json(res, schema=self._vod_api_schema)
+            res = self.session.http.get(self.VOD_API_URL.format(video_id))
+            stream_data = self.session.http.json(res, schema=self._vod_api_schema)
 
             # Check whether video format is expired
             current_date = datetime.strptime(stream_data['current_date'], '%Y-%m-%dT%H:%M:%S.%f')
@@ -88,12 +88,12 @@ class RTE(Plugin):
             # Live
             channel_id = match.group('channel_id')
             # Get live streams for desktop
-            res = http.get(self.LIVE_API_URL, params={'channelid': channel_id})
-            streams = http.xml(res, schema=self._live_api_schema)
+            res = self.session.http.get(self.LIVE_API_URL, params={'channelid': channel_id})
+            streams = self.session.http.xml(res, schema=self._live_api_schema)
 
             # Get HLS streams for Iphone
-            res = http.get(self.LIVE_API_URL, params={'channelid': channel_id, 'platform': 'iphone'})
-            stream = http.json(res, schema=self._live_api_iphone_schema)
+            res = self.session.http.get(self.LIVE_API_URL, params={'channelid': channel_id, 'platform': 'iphone'})
+            stream = self.session.http.json(res, schema=self._live_api_iphone_schema)
             if stream != 'none':
                 streams.append(stream)
 
diff --git a/src/streamlink/plugins/rtlxl.py b/src/streamlink/plugins/rtlxl.py
index 28c63778..453ba62a 100644
--- a/src/streamlink/plugins/rtlxl.py
+++ b/src/streamlink/plugins/rtlxl.py
@@ -2,7 +2,7 @@ import re
 import json
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream, RTMPStream
 
 _url_re = re.compile(r"http(?:s)?://(?:\w+\.)?rtl.nl/video/(?P<uuid>.*?)\Z", re.IGNORECASE)
@@ -16,7 +16,7 @@ class rtlxl(Plugin):
     def _get_streams(self):
         match = _url_re.match(self.url)
         uuid = match.group("uuid")
-        videourlfeed = http.get('https://tm-videourlfeed.rtl.nl/api/url/{}?device=pc&drm&format=hls'.format(uuid)).text
+        videourlfeed = self.session.http.get('https://tm-videourlfeed.rtl.nl/api/url/{}?device=pc&drm&format=hls'.format(uuid)).text
 
         videourlfeedjson = json.loads(videourlfeed)
         playlist_url = videourlfeedjson["url"]
diff --git a/src/streamlink/plugins/rtpplay.py b/src/streamlink/plugins/rtpplay.py
index a8cf9ad1..e484c250 100644
--- a/src/streamlink/plugins/rtpplay.py
+++ b/src/streamlink/plugins/rtpplay.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
 
@@ -19,7 +19,7 @@ class RTPPlay(Plugin):
             "User-Agent": useragents.CHROME
         }
 
-        res = http.get(self.url, headers=headers)
+        res = self.session.http.get(self.url, headers=headers)
 
         url_match = RTPPlay._m3u8_re.search(res.text)
 
diff --git a/src/streamlink/plugins/rtve.py b/src/streamlink/plugins/rtve.py
index 0fba6c9b..d4fcb6ac 100644
--- a/src/streamlink/plugins/rtve.py
+++ b/src/streamlink/plugins/rtve.py
@@ -4,10 +4,8 @@ from functools import partial
 
 from Crypto.Cipher import Blowfish
 
-from streamlink import PluginError
 from streamlink.compat import bytes, is_py3
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -20,8 +18,9 @@ class ZTNRClient(object):
     base_url = "http://ztnr.rtve.es/ztnr/res/"
     block_size = 16
 
-    def __init__(self, key):
+    def __init__(self, key, session):
         self.cipher = Blowfish.new(key, Blowfish.MODE_ECB)
+        self.session = session
 
     @classmethod
     def pad(cls, data):
@@ -42,7 +41,7 @@ class ZTNRClient(object):
         return self.unpad(self.cipher.decrypt(base64.b64decode(data, altchars=b"-_")))
 
     def request(self, data, *args, **kwargs):
-        res = http.get(self.base_url + self.encrypt(data), *args, **kwargs)
+        res = self.session.http.get(self.base_url + self.encrypt(data), *args, **kwargs)
         return self.decrypt(res.content)
 
     def get_cdn_list(self, vid, manager="apedemak", vtype="video", lang="es", schema=None):
@@ -114,21 +113,21 @@ class Rtve(Plugin):
 
     def __init__(self, url):
         Plugin.__init__(self, url)
-        self.zclient = ZTNRClient(self.secret_key)
-        http.headers = {"User-Agent": useragents.SAFARI_8}
+        self.session.http.headers = {"User-Agent": useragents.SAFARI_8}
+        self.zclient = ZTNRClient(self.secret_key, self.session)
 
     def _get_content_id(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.content_id_re.search(res.text)
         return m and int(m.group(1))
 
     def _get_subtitles(self, content_id):
-        res = http.get(self.subtitles_api.format(id=content_id))
-        return http.json(res, schema=self.subtitles_schema)
+        res = self.session.http.get(self.subtitles_api.format(id=content_id))
+        return self.session.http.json(res, schema=self.subtitles_schema)
 
     def _get_quality_map(self, content_id):
-        res = http.get(self.video_api.format(id=content_id))
-        data = http.json(res, schema=self.video_schema)
+        res = self.session.http.get(self.video_api.format(id=content_id))
+        data = self.session.http.json(res, schema=self.video_schema)
         qmap = {}
         for item in data["qualities"]:
             qname = {"MED": "Media", "HIGH": "Alta", "ORIGINAL": "Original"}.get(item["preset"], item["preset"])
@@ -150,8 +149,8 @@ class Rtve(Plugin):
                             streams.extend(HLSStream.parse_variant_playlist(self.session, url).items())
                         except (IOError, OSError):
                             self.logger.debug("Failed to load m3u8 url: {0}", url)
-                    elif ((url.endswith("mp4") or url.endswith("mov") or url.endswith("avi")) and
-                                  http.head(url, raise_for_status=False).status_code == 200):
+                    elif ((url.endswith("mp4") or url.endswith("mov") or url.endswith("avi"))
+                          and self.session.http.head(url, raise_for_status=False).status_code == 200):
                         if quality_map is None:  # only make the request when it is necessary
                             quality_map = self._get_quality_map(content_id)
                         # rename the HTTP sources to match the HLS sources
diff --git a/src/streamlink/plugins/rtvs.py b/src/streamlink/plugins/rtvs.py
index b2e03c09..67cbedb3 100644
--- a/src/streamlink/plugins/rtvs.py
+++ b/src/streamlink/plugins/rtvs.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream, HLSStream
 
 RUURL = "b=chrome&p=win&v=56&f=0&d=1"
@@ -40,13 +40,13 @@ class Rtvs(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _playlist_url_re.search(res.text)
         if match is None:
             return
 
-        res = http.get(match.group(1) + RUURL)
-        sources = http.json(res, schema=_playlist_schema)
+        res = self.session.http.get(match.group(1) + RUURL)
+        sources = self.session.http.json(res, schema=_playlist_schema)
 
         streams = {}
 
diff --git a/src/streamlink/plugins/ruv.py b/src/streamlink/plugins/ruv.py
index 5873d330..5f01ec33 100644
--- a/src/streamlink/plugins/ruv.py
+++ b/src/streamlink/plugins/ruv.py
@@ -5,7 +5,6 @@ import re
 from streamlink.plugin import Plugin
 from streamlink.stream import HLSStream
 
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 
 # URL to the RUV LIVE API
@@ -82,10 +81,10 @@ class Ruv(Plugin):
 
     def _get_live_streams(self):
         # Get JSON API
-        res = http.get(RUV_LIVE_API.format(self.stream_id))
+        res = self.session.http.get(RUV_LIVE_API.format(self.stream_id))
 
         # Parse the JSON API
-        json_res = http.json(res)
+        json_res = self.session.http.json(res)
 
         for url in json_res["result"]:
             if url.startswith("rtmp:"):
@@ -99,7 +98,7 @@ class Ruv(Plugin):
 
     def _get_sarpurinn_streams(self):
         # Get HTML page
-        res = http.get(self.url).text
+        res = self.session.http.get(self.url).text
         lines = "\n".join([l for l in res.split("\n") if "video.src" in l])
         multi_stream_match = _multi_re.search(lines)
 
diff --git a/src/streamlink/plugins/schoolism.py b/src/streamlink/plugins/schoolism.py
index 9632697f..c71ff0dd 100644
--- a/src/streamlink/plugins/schoolism.py
+++ b/src/streamlink/plugins/schoolism.py
@@ -4,7 +4,6 @@ import re
 from functools import partial
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -83,7 +82,7 @@ class Schoolism(Plugin):
         :return: (str) users email
         """
         if self.options.get("email") and self.options.get("password"):
-            res = http.post(self.login_url, data={"email": email,
+            res = self.session.http.post(self.login_url, data={"email": email,
                                                   "password": password,
                                                   "redirect": None,
                                                   "submit": "Login"})
@@ -99,7 +98,7 @@ class Schoolism(Plugin):
         user = self.login(self.options.get("email"), self.options.get("password"))
         if user:
             self.logger.debug("Logged in to Schoolism as {0}", user)
-            res = http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
+            res = self.session.http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
             lesson_playlist = self.playlist_schema.validate(res.text)
 
             part = self.options.get("part")
@@ -108,7 +107,7 @@ class Schoolism(Plugin):
             found = False
 
             # make request to key-time api, to get key specific headers
-            res = http.get(self.key_time_url, headers={"User-Agent": useragents.SAFARI_8})
+            res = self.session.http.get(self.key_time_url, headers={"User-Agent": useragents.SAFARI_8})
 
             for i, video in enumerate(lesson_playlist, 1):
                 if video["sources"] and i == part:
diff --git a/src/streamlink/plugins/seetv.py b/src/streamlink/plugins/seetv.py
index 3d1a1c74..6e766bc8 100644
--- a/src/streamlink/plugins/seetv.py
+++ b/src/streamlink/plugins/seetv.py
@@ -4,7 +4,6 @@ import time
 
 from streamlink import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -39,12 +38,12 @@ class SeeTV(Plugin):
         return self._url_re.match(self.url).group(1)
 
     def _get_tv_link(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         link_m = self._main_source_re.search(res.text)
         return link_m and link_m.group(1)
 
     def _get_streams(self):
-        http.headers.update({"User-Agent": useragents.CHROME,
+        self.session.http.headers.update({"User-Agent": useragents.CHROME,
                              "Referer": self.referer})
         fragment = dict(parse_qsl(urlparse(self.url).fragment))
         link = fragment.get("link")
@@ -57,12 +56,12 @@ class SeeTV(Plugin):
 
         player_url = self._api_url.format(link)
         self.logger.debug("Requesting player API: {0} (referer={1})", player_url, self.referer)
-        res = http.get(player_url,
+        res = self.session.http.get(player_url,
                        params={"_": int(time.time() * 1000)},
                        headers={"X-Requested-With": "XMLHttpRequest"})
 
         try:
-            data = http.json(res, schema=self.api_schema)
+            data = self.session.http.json(res, schema=self.api_schema)
         except PluginError as e:
             print(e)
             self.logger.error("Cannot play this stream type")
diff --git a/src/streamlink/plugins/showroom.py b/src/streamlink/plugins/showroom.py
index e0f264c4..0ee13cd5 100644
--- a/src/streamlink/plugins/showroom.py
+++ b/src/streamlink/plugins/showroom.py
@@ -2,7 +2,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.stream import HLSStream, RTMPStream
 
 _url_re = re.compile(r'''^https?://
@@ -119,7 +119,7 @@ class Showroom(Plugin):
         if match_dict['room_id'] is not None:
             return match_dict['room_id']
         else:
-            res = http.get(self.url, headers=self._headers)
+            res = self.session.http.get(self.url, headers=self._headers)
             match = _room_id_re.search(res.text)
             if not match:
                 title = self.url.rsplit('/', 1)[-1]
@@ -131,8 +131,8 @@ class Showroom(Plugin):
             return match.group('room_id')
 
     def _get_stream_info(self, room_id):
-        res = http.get(_api_stream_url.format(room_id=room_id), headers=self._headers)
-        return http.json(res, schema=_api_stream_schema)
+        res = self.session.http.get(_api_stream_url.format(room_id=room_id), headers=self._headers)
+        return self.session.http.json(res, schema=_api_stream_schema)
 
     def _get_rtmp_stream(self, stream_info):
         rtmp_url = '/'.join((stream_info['url'], stream_info['stream_name']))
diff --git a/src/streamlink/plugins/skai.py b/src/streamlink/plugins/skai.py
index 1459d1f1..61fba7ec 100644
--- a/src/streamlink/plugins/skai.py
+++ b/src/streamlink/plugins/skai.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 
 YOUTUBE_URL = "https://www.youtube.com/watch?v={0}"
 _url_re = re.compile(r'http(s)?://www\.skai.gr/.*')
@@ -26,7 +26,7 @@ class Skai(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        channel_id = http.get(self.url, schema=_youtube_url_schema)
+        channel_id = self.session.http.get(self.url, schema=_youtube_url_schema)
         if channel_id:
             return self.session.streams(YOUTUBE_URL.format(channel_id))
 
diff --git a/src/streamlink/plugins/sportal.py b/src/streamlink/plugins/sportal.py
index 3c1feda4..977a4dc0 100644
--- a/src/streamlink/plugins/sportal.py
+++ b/src/streamlink/plugins/sportal.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream
 from streamlink.plugins.common_jwplayer import _js_to_json
@@ -38,7 +37,7 @@ class Sportal(Plugin):
 
     @Plugin.broken(1165)
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         playlist = self._playlist_schema.validate(res.text)
         if playlist:
diff --git a/src/streamlink/plugins/sportschau.py b/src/streamlink/plugins/sportschau.py
index cfb623b3..1b6d1599 100644
--- a/src/streamlink/plugins/sportschau.py
+++ b/src/streamlink/plugins/sportschau.py
@@ -2,7 +2,6 @@ import re
 import json
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HDSStream
 from streamlink.utils import update_scheme
 
@@ -16,7 +15,7 @@ class sportschau(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _player_js.search(res.text)
         if match:
             player_js = match.group(0)
@@ -25,7 +24,7 @@ class sportschau(Plugin):
             self.logger.info("Didn't find player js. Probably this page doesn't contain a video")
             return
 
-        res = http.get(player_js)
+        res = self.session.http.get(player_js)
 
         jsonp_start = res.text.find('(') + 1
         jsonp_end = res.text.rfind(')')
diff --git a/src/streamlink/plugins/srgssr.py b/src/streamlink/plugins/srgssr.py
index 218075c3..965680db 100644
--- a/src/streamlink/plugins/srgssr.py
+++ b/src/streamlink/plugins/srgssr.py
@@ -5,7 +5,6 @@ import re
 from streamlink import PluginError
 from streamlink.compat import urlparse, parse_qsl, urlencode, urlunparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -61,7 +60,7 @@ class SRGSSR(Plugin):
         elif url_m.group(2):
             site, video_id = url_m.group(1), url_m.group(2)
         else:
-            video_id_m = http.get(self.url, schema=self.video_id_schema)
+            video_id_m = self.session.http.get(self.url, schema=self.video_id_schema)
             if video_id_m:
                 site, video_id = video_id_m.groups()
 
@@ -70,8 +69,8 @@ class SRGSSR(Plugin):
     def auth_url(self, url):
         parsed = urlparse(url)
         path, _ = parsed.path.rsplit("/", 1)
-        token_res = http.get(self.token_url, params=dict(acl=path + "/*"))
-        authparams = http.json(token_res, schema=self.token_schema)
+        token_res = self.session.http.get(self.token_url, params=dict(acl=path + "/*"))
+        authparams = self.session.http.json(token_res, schema=self.token_schema)
 
         existing = dict(parse_qsl(parsed.query))
         existing.update(dict(parse_qsl(authparams)))
@@ -85,11 +84,11 @@ class SRGSSR(Plugin):
             self.logger.debug("Found {0} video ID {1}", site, video_id)
 
             try:
-                res = http.get(self.api_url.format(site=site, id=video_id))
+                res = self.session.http.get(self.api_url.format(site=site, id=video_id))
             except PluginError:
                 return
 
-            for stream_info in http.json(res, schema=self.api_schema):
+            for stream_info in self.session.http.json(res, schema=self.api_schema):
                 for url in stream_info["url"]:
                     if stream_info["@protocol"] == "HTTP-HLS":
                         for s in HLSStream.parse_variant_playlist(self.session, self.auth_url(url["text"])).items():
diff --git a/src/streamlink/plugins/ssh101.py b/src/streamlink/plugins/ssh101.py
index 14ff0905..34dc879e 100644
--- a/src/streamlink/plugins/ssh101.py
+++ b/src/streamlink/plugins/ssh101.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 from streamlink.compat import urljoin
 
@@ -17,13 +16,13 @@ class SSH101(Plugin):
 
     @Plugin.broken(1176)
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         # some pages have embedded players
         iframe_m = self.iframe_re.search(res.text)
         if iframe_m:
             url = urljoin(self.url, iframe_m.group("url"))
-            res = http.get(url)
+            res = self.session.http.get(url)
 
         video = self.src_re.search(res.text)
         stream_src = video and video.group("url")
diff --git a/src/streamlink/plugins/startv.py b/src/streamlink/plugins/startv.py
index b136c6b0..6743336a 100644
--- a/src/streamlink/plugins/startv.py
+++ b/src/streamlink/plugins/startv.py
@@ -3,7 +3,6 @@ import re
 
 from streamlink import streams
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 
 
@@ -16,7 +15,7 @@ class StarTV(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.iframe_re.search(res.text)
 
         yt_url = m and m.group(1)
diff --git a/src/streamlink/plugins/steam.py b/src/streamlink/plugins/steam.py
index fcbf0ce5..453ae4b3 100644
--- a/src/streamlink/plugins/steam.py
+++ b/src/streamlink/plugins/steam.py
@@ -9,7 +9,6 @@ from Crypto.PublicKey import RSA
 import streamlink
 from streamlink.exceptions import FatalPluginError
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.plugin.api.validate import Schema
 from streamlink.stream.dash import DASHStream
@@ -74,7 +73,7 @@ class SteamBroadcastPlugin(Plugin):
 
     def __init__(self, url):
         super(SteamBroadcastPlugin, self).__init__(url)
-        http.headers["User-Agent"] = self._user_agent
+        self.session.http.headers["User-Agent"] = self._user_agent
 
     @classmethod
     def can_handle_url(cls, url):
@@ -91,8 +90,8 @@ class SteamBroadcastPlugin(Plugin):
         :param password: password for account
         :return: encrypted password
         """
-        res = http.get(self._get_rsa_key_url, params=dict(username=email, donotcache=self.donotcache))
-        rsadata = http.json(res, schema=self._rsa_key_schema)
+        res = self.session.http.get(self._get_rsa_key_url, params=dict(username=email, donotcache=self.donotcache))
+        rsadata = self.session.http.json(res, schema=self._rsa_key_schema)
 
         rsa = RSA.construct((rsadata["publickey_mod"], rsadata["publickey_exp"]))
         cipher = PKCS1_v1_5.new(rsa)
@@ -119,9 +118,9 @@ class SteamBroadcastPlugin(Plugin):
             "twofactorcode": twofactorcode
         }
 
-        res = http.post(self._dologin_url, data=login_data)
+        res = self.session.http.post(self._dologin_url, data=login_data)
 
-        resp = http.json(res, schema=self._dologin_schema)
+        resp = self.session.http.json(res, schema=self._dologin_schema)
 
         if not resp[u"success"]:
             if resp.get(u"captcha_needed"):
@@ -177,11 +176,11 @@ class SteamBroadcastPlugin(Plugin):
         return self.dologin(email, password)
 
     def _get_broadcast_stream(self, steamid, viewertoken=0):
-        res = http.get(self._get_broadcast_url,
+        res = self.session.http.get(self._get_broadcast_url,
                        params=dict(broadcastid=0,
                                    steamid=steamid,
                                    viewertoken=viewertoken))
-        return http.json(res, schema=self._broadcast_schema)
+        return self.session.http.json(res, schema=self._broadcast_schema)
 
     def _get_streams(self):
         streamdata = None
diff --git a/src/streamlink/plugins/streamable.py b/src/streamlink/plugins/streamable.py
index 52d9a61a..e49be7a4 100644
--- a/src/streamlink/plugins/streamable.py
+++ b/src/streamlink/plugins/streamable.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream
 from streamlink.utils import parse_json, update_scheme
 
@@ -29,7 +29,7 @@ class Streamable(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        data = http.get(self.url, schema=self.config_schema)
+        data = self.session.http.get(self.url, schema=self.config_schema)
 
         for info in data["files"].values():
             stream_url = update_scheme(self.url, info["url"])
diff --git a/src/streamlink/plugins/streamboat.py b/src/streamlink/plugins/streamboat.py
index b95abbe5..b23aa236 100644
--- a/src/streamlink/plugins/streamboat.py
+++ b/src/streamlink/plugins/streamboat.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 _RE_URL = re.compile(r'^https?://streamboat.tv/.+')
@@ -16,7 +15,7 @@ class StreamBoat(Plugin):
         return bool(_RE_URL.match(url))
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         text = res.text
         cdn = _RE_CDN.search(text).group(1)
         playlist_url = _RE_PLAYLIST.search(text).group(1)
diff --git a/src/streamlink/plugins/streamingvideoprovider.py b/src/streamlink/plugins/streamingvideoprovider.py
index c4a7a3ff..e7cfb0f7 100644
--- a/src/streamlink/plugins/streamingvideoprovider.py
+++ b/src/streamlink/plugins/streamingvideoprovider.py
@@ -3,7 +3,7 @@ import re
 from time import time
 
 from streamlink.plugin import Plugin, PluginError
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream, HLSStream
 
 SWF_URL = "http://play.streamingvideoprovider.com/player2.swf"
@@ -45,7 +45,7 @@ class Streamingvideoprovider(Plugin):
             "file": channel_name,
             "rid": time()
         }
-        playlist_url = http.get(API_URL, params=params, schema=_hls_schema)
+        playlist_url = self.session.http.get(API_URL, params=params, schema=_hls_schema)
         if not playlist_url:
             return
 
@@ -58,8 +58,8 @@ class Streamingvideoprovider(Plugin):
             "clip_id": channel_name,
             "rid": time()
         }
-        res = http.get(API_URL, params=params)
-        rtmp_url = http.xml(res, schema=_rtmp_schema)
+        res = self.session.http.get(API_URL, params=params)
+        rtmp_url = self.session.http.xml(res, schema=_rtmp_schema)
 
         return RTMPStream(self.session, {
             "rtmp": rtmp_url,
diff --git a/src/streamlink/plugins/streamme.py b/src/streamlink/plugins/streamme.py
index c01b9938..3e78c371 100644
--- a/src/streamlink/plugins/streamme.py
+++ b/src/streamlink/plugins/streamme.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 _RE_URL = re.compile(r'^https?://(?:www.)stream.me/(\w+).*$')
@@ -16,7 +15,7 @@ class StreamMe(Plugin):
     def _get_streams(self):
         username = _RE_URL.match(self.url).group(1)
         url = 'https://www.stream.me/api-user/v1/{0}/channel'.format(username)
-        data = http.get(url).json()
+        data = self.session.http.get(url).json()
         try:
             m3u8 = data['_embedded']['streams'][0]['_links']['hlsmp4']['href']
             return HLSStream.parse_variant_playlist(self.session, m3u8)
diff --git a/src/streamlink/plugins/streann.py b/src/streamlink/plugins/streann.py
index 3667dd23..664e089d 100644
--- a/src/streamlink/plugins/streann.py
+++ b/src/streamlink/plugins/streann.py
@@ -8,7 +8,6 @@ import re
 
 from streamlink.compat import urlparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_qsd
@@ -45,13 +44,13 @@ class Streann(Plugin):
 
     @property
     def time(self):
-        res = http.get(self.get_time_url, headers=self._headers)
-        data = http.json(res)
+        res = self.session.http.get(self.get_time_url, headers=self._headers)
+        data = self.session.http.json(res)
         return str(data.get("serverTime", int(time.time() * 1000)))
 
     def passphrase(self):
         self.logger.debug("passphrase ...")
-        res = http.get(self.url, headers=self._headers)
+        res = self.session.http.get(self.url, headers=self._headers)
         passphrase_m = self.passphrase_re.search(res.text)
         return passphrase_m and passphrase_m.group("passphrase").encode("utf8")
 
@@ -67,9 +66,9 @@ class Streann(Plugin):
             "Content-Type": "application/x-www-form-urlencoded"
         }
 
-        res = http.post(self.token_url.format(deviceId=self.device_id, **config),
+        res = self.session.http.post(self.token_url.format(deviceId=self.device_id, **config),
                         data=pdata, headers=headers)
-        data = http.json(res)
+        data = self.session.http.json(res)
         return data["token"]
 
     def _get_streams(self):
diff --git a/src/streamlink/plugins/svtplay.py b/src/streamlink/plugins/svtplay.py
index 28b1e1cc..bcc56dbd 100644
--- a/src/streamlink/plugins/svtplay.py
+++ b/src/streamlink/plugins/svtplay.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import StreamMapper, http, validate
+from streamlink.plugin.api import StreamMapper, validate
 from streamlink.stream import HLSStream, HDSStream
 
 API_URL = "http://www.svt.se/videoplayer-api/video/{0}"
@@ -66,21 +66,21 @@ class SVTPlay(Plugin):
 
     def _get_streams(self):
         # Retrieve URL page and search for new type of video ID
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _id_re.search(res.text)
 
         # Use API if match, otherwise resort to old method
         if match:
             vid = match.group("id")
-            res = http.get(API_URL.format(vid))
+            res = self.session.http.get(API_URL.format(vid))
 
-            videos = http.json(res, schema=_video_schema)
+            videos = self.session.http.json(res, schema=_video_schema)
             mapper = StreamMapper(cmp=lambda format, video: video["format"] == format)
             mapper.map("hls", self._create_streams, "HLS", HLSStream.parse_variant_playlist)
             mapper.map("hds", self._create_streams, "HDS", HDSStream.parse_manifest)
         else:
-            res = http.get(self.url, params=dict(output="json"))
-            videos = http.json(res, schema=_old_video_schema)
+            res = self.session.http.get(self.url, params=dict(output="json"))
+            videos = self.session.http.json(res, schema=_old_video_schema)
 
             mapper = StreamMapper(cmp=lambda type, video: video["playerType"] == type)
             mapper.map("ios", self._create_streams, "HLS", HLSStream.parse_variant_playlist)
diff --git a/src/streamlink/plugins/swisstxt.py b/src/streamlink/plugins/swisstxt.py
index cacf8c0b..84ad9a01 100644
--- a/src/streamlink/plugins/swisstxt.py
+++ b/src/streamlink/plugins/swisstxt.py
@@ -4,7 +4,6 @@ import re
 
 from streamlink.compat import urlparse, parse_qsl, urlunparse
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 
@@ -29,7 +28,7 @@ class Swisstxt(Plugin):
         api_url = self.api_url.format(id=event_id, site=site.upper())
         self.logger.debug("Calling API: {0}", api_url)
 
-        stream_url = http.get(api_url).text.strip("\"'")
+        stream_url = self.session.http.get(api_url).text.strip("\"'")
 
         parsed = urlparse(stream_url)
         query = dict(parse_qsl(parsed.query))
diff --git a/src/streamlink/plugins/teamliquid.py b/src/streamlink/plugins/teamliquid.py
index d0139b34..c629b1ea 100644
--- a/src/streamlink/plugins/teamliquid.py
+++ b/src/streamlink/plugins/teamliquid.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 
 
 _url_re = re.compile(r'''https?://(?:www\.)?teamliquid\.net/video/streams/''')
@@ -13,7 +12,7 @@ class Teamliquid(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         stream_address_re = re.compile(r'''href\s*=\s*"([^"]+)"\s*>\s*View on''')
 
diff --git a/src/streamlink/plugins/telefe.py b/src/streamlink/plugins/telefe.py
index 6a5053a2..ddca29ab 100644
--- a/src/streamlink/plugins/telefe.py
+++ b/src/streamlink/plugins/telefe.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream, HTTPStream
 from streamlink.utils import parse_json
 
@@ -14,7 +14,7 @@ class Telefe(Plugin):
         return cls._url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url, headers={'User-Agent': useragents.CHROME})
+        res = self.session.http.get(self.url, headers={'User-Agent': useragents.CHROME})
         video_search = res.text
         video_search = video_search[video_search.index('{"top":{"view":"PlayerContainer","model":{'):]
         video_search = video_search[: video_search.index('}]}}') + 4] + "}"
@@ -33,7 +33,7 @@ class Telefe(Plugin):
                 video_url_found_http = "http://telefe.com" + current_video_source["url"]
                 self.logger.debug("HTTP content available")
 
-        http.headers = {'Referer': self.url,
+        self.session.http.headers = {'Referer': self.url,
                         'User-Agent': useragents.CHROME,
                         'X-Requested-With': 'ShockwaveFlash/25.0.0.148'}
 
diff --git a/src/streamlink/plugins/tf1.py b/src/streamlink/plugins/tf1.py
index 88b5e585..072bb889 100644
--- a/src/streamlink/plugins/tf1.py
+++ b/src/streamlink/plugins/tf1.py
@@ -3,7 +3,7 @@ import re
 
 from streamlink.compat import urlparse, parse_qsl
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HDSStream
 from streamlink.stream import HLSStream
 
@@ -31,7 +31,7 @@ class TF1(Plugin):
     def _get_hds_streams(self, channel):
         channel = self.hds_channel_remap.get(channel, "{0}live".format(channel))
         self.logger.debug("Using HDS channel name: {0}".format(channel))
-        manifest_url = http.get(self.api_url.format(channel),
+        manifest_url = self.session.http.get(self.api_url.format(channel),
                                 params={"getURL": 1},
                                 headers={"User-Agent": useragents.FIREFOX}).text
 
@@ -46,7 +46,7 @@ class TF1(Plugin):
         embed_url = self.embed_url.format(channel)
         self.logger.debug("Found embed URL: {0}", embed_url)
         # page needs to have a mobile user agent
-        embed_page = http.get(embed_url, headers={"User-Agent": useragents.ANDROID})
+        embed_page = self.session.http.get(embed_url, headers={"User-Agent": useragents.ANDROID})
 
         m = self.embed_re.search(embed_page.text)
         if m:
diff --git a/src/streamlink/plugins/tga.py b/src/streamlink/plugins/tga.py
index 18788e0e..1f71f852 100644
--- a/src/streamlink/plugins/tga.py
+++ b/src/streamlink/plugins/tga.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_query
 from streamlink.stream import HLSStream, HTTPStream, RTMPStream
 
@@ -70,25 +70,25 @@ class Tga(Plugin):
             return "live"
 
     def _get_channel_id(self, domain):
-        channel_info = http.get(CHANNEL_INFO_URL % str(domain))
-        info = http.json(channel_info, schema=_channel_schema)
+        channel_info = self.session.http.get(CHANNEL_INFO_URL % str(domain))
+        info = self.session.http.json(channel_info, schema=_channel_schema)
         if info is None:
             return 0, 0
 
         return info['channel']['vid'], info['channel']['id']
 
     def _get_qq_streams(self, vid):
-        res = http.get(QQ_STREAM_INFO_URL % (vid, 1))
-        info = http.json(res, schema=_qq_schema)
+        res = self.session.http.get(QQ_STREAM_INFO_URL % (vid, 1))
+        info = self.session.http.json(res, schema=_qq_schema)
         yield "live", HTTPStream(self.session, info)
 
-        res = http.get(QQ_STREAM_INFO_URL % (vid, 2))
-        info = http.json(res, schema=_qq_schema)
+        res = self.session.http.get(QQ_STREAM_INFO_URL % (vid, 2))
+        info = self.session.http.json(res, schema=_qq_schema)
         yield "live", HLSStream(self.session, info)
 
     def _get_plu_streams(self, cid):
-        res = http.get(PLU_STREAM_INFO_URL % cid)
-        info = http.json(res, schema=_plu_schema)
+        res = self.session.http.get(PLU_STREAM_INFO_URL % cid)
+        info = self.session.http.json(res, schema=_plu_schema)
         for source in info["playLines"][0]["urls"]:
             quality = self._get_quality(source["resolution"])
             if source["ext"] == "m3u8":
diff --git a/src/streamlink/plugins/theplatform.py b/src/streamlink/plugins/theplatform.py
index 22e07583..5987face 100644
--- a/src/streamlink/plugins/theplatform.py
+++ b/src/streamlink/plugins/theplatform.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 
@@ -18,19 +17,19 @@ class ThePlatform(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.release_re.search(res.text)
         release_url = m and m.group(1)
         if release_url:
             api_url = release_url + "&formats=m3u,mpeg4"
-            res = http.get(api_url, allow_redirects=False, raise_for_status=False)
+            res = self.session.http.get(api_url, allow_redirects=False, raise_for_status=False)
             if res.status_code == 302:
                 stream_url = res.headers.get("Location")
                 return HLSStream.parse_variant_playlist(self.session, stream_url, headers={
                     "Referer": self.url
                 })
             else:
-                error = http.json(res)
+                error = self.session.http.json(res)
                 self.logger.error("{0}: {1}",
                                   error.get("title", "Error"),
                                   error.get("description", "An unknown error occurred"))
diff --git a/src/streamlink/plugins/tigerdile.py b/src/streamlink/plugins/tigerdile.py
index 59f33fc6..c1670cd5 100644
--- a/src/streamlink/plugins/tigerdile.py
+++ b/src/streamlink/plugins/tigerdile.py
@@ -2,7 +2,7 @@ import re
 import json
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream
 from streamlink.stream import HLSStream
 
@@ -26,7 +26,7 @@ class Tigerdile(Plugin):
         res = self.url
         streamname = _url_re.search(res).group(1)
 
-        ci = http.get(API_URL.format(channel=streamname))
+        ci = self.session.http.get(API_URL.format(channel=streamname))
         api_json = json.loads(ci.text)
 
         if not api_json or len(api_json) == 0:
diff --git a/src/streamlink/plugins/tlctr.py b/src/streamlink/plugins/tlctr.py
index c3f83ac7..b635e400 100644
--- a/src/streamlink/plugins/tlctr.py
+++ b/src/streamlink/plugins/tlctr.py
@@ -2,7 +2,6 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
@@ -20,8 +19,8 @@ class TLCtr(Plugin):
         return cls._url_re.match(url) is not None
 
     def _get_streams(self):
-        http.headers.update({'User-Agent': useragents.FIREFOX})
-        res = http.get(self.url)
+        self.session.http.headers.update({'User-Agent': useragents.FIREFOX})
+        res = self.session.http.get(self.url)
 
         m = self._hls_re.search(res.text)
         if not m:
diff --git a/src/streamlink/plugins/trt.py b/src/streamlink/plugins/trt.py
index 8dff9847..bca9b992 100644
--- a/src/streamlink/plugins/trt.py
+++ b/src/streamlink/plugins/trt.py
@@ -3,7 +3,6 @@ import re
 from base64 import b64decode
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.compat import urlparse, parse_qsl
 from streamlink.stream import HDSStream
@@ -29,7 +28,7 @@ class TRT(Plugin):
         args = dict(parse_qsl(urlparse(self.url).query))
         if "k" in args:
             self.logger.debug("Loading channel: {k}", **args)
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
             stream_data_m = self.stream_data_re.search(res.text)
             if stream_data_m:
                 script_vars = b64decode(stream_data_m.group(1)).decode("utf8")
diff --git a/src/streamlink/plugins/trtspor.py b/src/streamlink/plugins/trtspor.py
index 976af787..bb0af9e2 100644
--- a/src/streamlink/plugins/trtspor.py
+++ b/src/streamlink/plugins/trtspor.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import AkamaiHDStream
 from streamlink.stream import HDSStream
@@ -22,7 +21,7 @@ class TRTSpor(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         url_m = self.m3u8_re.search(res.text)
         hls_url = url_m and url_m.group("url")
         if hls_url:
diff --git a/src/streamlink/plugins/turkuvaz.py b/src/streamlink/plugins/turkuvaz.py
index 3d54adfd..59c24fed 100644
--- a/src/streamlink/plugins/turkuvaz.py
+++ b/src/streamlink/plugins/turkuvaz.py
@@ -1,7 +1,6 @@
 import random
 import re
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -42,12 +41,12 @@ class Turkuvaz(Plugin):
                    "minikacocuk": "minikagococuk"}.get(domain, domain)
         hls_url = self._hls_url.format(channel=channel)
         # get the secure HLS URL
-        res = http.get(self._token_url,
+        res = self.session.http.get(self._token_url,
                        params="url={0}".format(hls_url),
                        headers={"Referer": self.url,
                                 "User-Agent": useragents.CHROME})
 
-        secure_hls_url = http.json(res, schema=self._token_schema)
+        secure_hls_url = self.session.http.json(res, schema=self._token_schema)
 
         self.logger.debug("Found HLS URL: {0}".format(secure_hls_url))
         return HLSStream.parse_variant_playlist(self.session, secure_hls_url)
diff --git a/src/streamlink/plugins/tv1channel.py b/src/streamlink/plugins/tv1channel.py
index 377e4815..cc38ecb0 100644
--- a/src/streamlink/plugins/tv1channel.py
+++ b/src/streamlink/plugins/tv1channel.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 
 _url_re = re.compile(r'''https?://(www\.)?tv1channel\.org/''')
 _embed_re = re.compile(r'''<iframe.+src="([^"]+)"''')
@@ -13,7 +12,7 @@ class TV1Channel(Plugin):
         return _url_re.match(url)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _embed_re.search(res.text)
 
         if match:
diff --git a/src/streamlink/plugins/tv360.py b/src/streamlink/plugins/tv360.py
index 1c10467a..215afa81 100644
--- a/src/streamlink/plugins/tv360.py
+++ b/src/streamlink/plugins/tv360.py
@@ -3,7 +3,6 @@ import re
 from functools import partial
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
@@ -35,7 +34,7 @@ class TV360(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         data = self.data_schema.validate(res.text)
 
         if data:
diff --git a/src/streamlink/plugins/tv3cat.py b/src/streamlink/plugins/tv3cat.py
index 52f31ba3..9746400e 100644
--- a/src/streamlink/plugins/tv3cat.py
+++ b/src/streamlink/plugins/tv3cat.py
@@ -3,7 +3,6 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 from streamlink.plugin.api import validate
 
@@ -33,7 +32,7 @@ class TV3Cat(Plugin):
         if match:
             ident = match.group(1)
             data_url = self._stream_info_url.format(ident=ident)
-            stream_infos = http.json(http.get(data_url), schema=self._channel_schema)
+            stream_infos = self.session.http.json(self.session.http.get(data_url), schema=self._channel_schema)
 
             for stream in stream_infos:
                 try:
diff --git a/src/streamlink/plugins/tv4play.py b/src/streamlink/plugins/tv4play.py
index 7e131227..c2d3cb77 100644
--- a/src/streamlink/plugins/tv4play.py
+++ b/src/streamlink/plugins/tv4play.py
@@ -4,7 +4,7 @@ import re
 from streamlink.compat import urljoin
 from streamlink.exceptions import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
 log = logging.getLogger(__name__)
@@ -57,14 +57,14 @@ class TV4Play(Plugin):
             "service": "tv4",
         }
         try:
-            res = http.get(self.api_assets.format(self.get_video_id),
+            res = self.session.http.get(self.api_assets.format(self.get_video_id),
                            params=params)
         except Exception as e:
             if "404 Client Error" in str(e):
                 raise PluginError("This Video is not available")
             raise e
         log.debug("Found metadata")
-        metadata = http.json(res, schema=self._meta_schema)
+        metadata = self.session.http.json(res, schema=self._meta_schema)
         self.title = metadata["metadata"]["title"]
         return metadata
 
@@ -77,14 +77,14 @@ class TV4Play(Plugin):
         metadata = self.get_metadata()
 
         try:
-            res = http.get(urljoin(self.api_url, metadata["mediaUri"]))
+            res = self.session.http.get(urljoin(self.api_url, metadata["mediaUri"]))
         except Exception as e:
             if "401 Client Error" in str(e):
                 raise PluginError("This Video is not available in your country")
             raise e
 
         log.debug("Found stream data")
-        data = http.json(res)
+        data = self.session.http.json(res)
         hls_url = data["playbackItem"]["manifestUrl"]
         log.debug("URL={0}".format(hls_url))
         for s in HLSStream.parse_variant_playlist(self.session,
diff --git a/src/streamlink/plugins/tv5monde.py b/src/streamlink/plugins/tv5monde.py
index d6a57f14..99d88229 100644
--- a/src/streamlink/plugins/tv5monde.py
+++ b/src/streamlink/plugins/tv5monde.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream, HTTPStream, RTMPStream
 from streamlink.utils import parse_json
 from streamlink.plugins.common_jwplayer import _js_to_json
@@ -50,7 +50,7 @@ class TV5Monde(Plugin):
         if '.mp4' in url:
             return [url]
 
-        res = http.get(url)
+        res = self.session.http.get(url)
         videos = self._get_non_embed_streams(res.text)
         if videos:
             return videos
@@ -58,7 +58,7 @@ class TV5Monde(Plugin):
         return []
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = self._videos_re.search(res.text)
         if match is not None:
             videos = self._videos_schema.validate(match.group('videos'))
diff --git a/src/streamlink/plugins/tv8.py b/src/streamlink/plugins/tv8.py
index f23fc847..7b9f1b4c 100644
--- a/src/streamlink/plugins/tv8.py
+++ b/src/streamlink/plugins/tv8.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 
@@ -34,7 +33,7 @@ class TV8(Plugin):
         return cls.url_re.match(url) is not None
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         stream_url = self.player_config_schema.validate(res.text)
         if stream_url:
             return HLSStream.parse_variant_playlist(self.session, stream_url)
diff --git a/src/streamlink/plugins/tvcatchup.py b/src/streamlink/plugins/tvcatchup.py
index bd150295..8862a631 100644
--- a/src/streamlink/plugins/tvcatchup.py
+++ b/src/streamlink/plugins/tvcatchup.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.stream import HLSStream
 
 USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
@@ -18,8 +17,8 @@ class TVCatchup(Plugin):
         """
         Finds the streams from tvcatchup.com.
         """
-        http.headers.update({"User-Agent": USER_AGENT})
-        res = http.get(self.url)
+        self.session.http.headers.update({"User-Agent": USER_AGENT})
+        res = self.session.http.get(self.url)
 
         match = _stream_re.search(res.text, re.IGNORECASE | re.MULTILINE)
 
diff --git a/src/streamlink/plugins/tvnbg.py b/src/streamlink/plugins/tvnbg.py
index 0ac65610..48c0e7d5 100644
--- a/src/streamlink/plugins/tvnbg.py
+++ b/src/streamlink/plugins/tvnbg.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.compat import urljoin
 from streamlink.stream import HLSStream
 
@@ -17,14 +16,14 @@ class TVNBG(Plugin):
 
     def _get_streams(self):
         base_url = self.url
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         # Search for the iframe in the page
         iframe_m = self.iframe_re.search(res.text)
         if iframe_m:
             # If the iframe is found, load the embedded page
             base_url = iframe_m.group(1)
-            res = http.get(iframe_m.group(1))
+            res = self.session.http.get(iframe_m.group(1))
 
         # Search the page (original or embedded) for the stream URL
         src_m = self.src_re.search(res.text)
diff --git a/src/streamlink/plugins/tvp.py b/src/streamlink/plugins/tvp.py
index 557feffa..b96eded3 100644
--- a/src/streamlink/plugins/tvp.py
+++ b/src/streamlink/plugins/tvp.py
@@ -2,7 +2,6 @@ import re
 
 from streamlink.exceptions import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.stream import HTTPStream
@@ -24,7 +23,7 @@ class TVP(Plugin):
         return cls._url_re.match(url) is not None
 
     def get_embed_url(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         m = self._video_id_re.search(res.text)
         if not m:
@@ -36,10 +35,10 @@ class TVP(Plugin):
         return p_url
 
     def _get_streams(self):
-        http.headers.update({'User-Agent': useragents.FIREFOX})
+        self.session.http.headers.update({'User-Agent': useragents.FIREFOX})
 
         embed_url = self.get_embed_url()
-        res = http.get(embed_url)
+        res = self.session.http.get(embed_url)
         m = self._stream_re.findall(res.text)
         if not m:
             raise PluginError('Unable to find a stream url')
diff --git a/src/streamlink/plugins/tvplayer.py b/src/streamlink/plugins/tvplayer.py
index bfc678d9..aafdf618 100644
--- a/src/streamlink/plugins/tvplayer.py
+++ b/src/streamlink/plugins/tvplayer.py
@@ -2,7 +2,7 @@
 import re
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
@@ -54,13 +54,13 @@ class TVPlayer(Plugin):
 
     def __init__(self, url):
         super(TVPlayer, self).__init__(url)
-        http.headers.update({"User-Agent": useragents.CHROME})
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
 
     def authenticate(self, username, password):
-        res = http.get(self.login_url)
+        res = self.session.http.get(self.login_url)
         match = self.login_token_re.search(res.text)
         token = match and match.group(1)
-        res2 = http.post(self.login_url, data=dict(email=username, password=password, token=token),
+        res2 = self.session.http.post(self.login_url, data=dict(email=username, password=password, token=token),
                          allow_redirects=False)
         # there is a 302 redirect on a successful login
         return res2.status_code == 302
@@ -68,13 +68,13 @@ class TVPlayer(Plugin):
     def _get_stream_data(self, resource, channel_id, token, service=1):
         # Get the context info (validation token and platform)
         self.logger.debug("Getting stream information for resource={0}".format(resource))
-        context_res = http.get(self.context_url, params={"resource": resource,
+        context_res = self.session.http.get(self.context_url, params={"resource": resource,
                                                          "gen": token})
-        context_data = http.json(context_res, schema=self.context_schema)
+        context_data = self.session.http.json(context_res, schema=self.context_schema)
         self.logger.debug("Context data: {0}", str(context_data))
 
         # get the stream urls
-        res = http.post(self.api_url, data=dict(
+        res = self.session.http.post(self.api_url, data=dict(
             service=service,
             id=channel_id,
             validate=context_data["validate"],
@@ -82,7 +82,7 @@ class TVPlayer(Plugin):
             platform=context_data["platform"]["key"]),
             raise_for_status=False)
 
-        return http.json(res, schema=self.stream_schema)
+        return self.session.http.json(res, schema=self.stream_schema)
 
     def _get_stream_attrs(self, page):
         stream_attrs = dict((k.replace("-", "_"), v.strip('"')) for k, v in self.stream_attrs_re.findall(page.text))
@@ -108,12 +108,12 @@ class TVPlayer(Plugin):
 
         # find the list of channels from the html in the page
         self.url = self.url.replace("https", "http")  # https redirects to http
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         if "enter your postcode" in res.text:
             self.logger.info("Setting your postcode to: {0}. "
                              "This can be changed in the settings on tvplayer.com", self.dummy_postcode)
-            res = http.post(self.update_url,
+            res = self.session.http.post(self.update_url,
                             data=dict(postcode=self.dummy_postcode),
                             params=dict(return_url=self.url))
 
diff --git a/src/streamlink/plugins/tvrby.py b/src/streamlink/plugins/tvrby.py
index 66aac64e..a6bbc463 100644
--- a/src/streamlink/plugins/tvrby.py
+++ b/src/streamlink/plugins/tvrby.py
@@ -2,7 +2,6 @@ from __future__ import print_function
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.stream import RTMPStream
@@ -32,7 +31,7 @@ class TVRBy(Plugin):
 
     @Plugin.broken()
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         stream_urls = self.stream_schema.validate(res.text)
         self.logger.debug("Found {0} stream URL{1}", len(stream_urls),
                           "" if len(stream_urls) == 1 else "s")
diff --git a/src/streamlink/plugins/tvrplus.py b/src/streamlink/plugins/tvrplus.py
index 7784666d..52e400fd 100644
--- a/src/streamlink/plugins/tvrplus.py
+++ b/src/streamlink/plugins/tvrplus.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -27,7 +26,7 @@ class TVRPlus(Plugin):
             "User-Agent": useragents.FIREFOX,
             "Referer": self.url
         }
-        stream_url = self.stream_schema.validate(http.get(self.url).text)
+        stream_url = self.stream_schema.validate(self.session.http.get(self.url).text)
         if stream_url:
             stream_url = list(set(stream_url))
             for url in stream_url:
diff --git a/src/streamlink/plugins/tvtoya.py b/src/streamlink/plugins/tvtoya.py
index a5b04583..da3821f8 100644
--- a/src/streamlink/plugins/tvtoya.py
+++ b/src/streamlink/plugins/tvtoya.py
@@ -2,7 +2,7 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 from streamlink.utils import update_scheme
 
@@ -19,7 +19,7 @@ class TVToya(Plugin):
 
     def _get_streams(self):
         self.session.set_option('hls-live-edge', 10)
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         playlist_m = self._playlist_re.search(res.text)
 
         if playlist_m:
diff --git a/src/streamlink/plugins/twitch.py b/src/streamlink/plugins/twitch.py
index f1efb7e8..4ef9487f 100644
--- a/src/streamlink/plugins/twitch.py
+++ b/src/streamlink/plugins/twitch.py
@@ -8,7 +8,7 @@ import requests
 from streamlink.compat import urlparse
 from streamlink.exceptions import NoStreamsError, PluginError, StreamError
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_json, parse_query
 from streamlink.stream import (
     HTTPStream, HLSStream, FLVPlaylist, extract_flv_header_tags
@@ -129,6 +129,9 @@ _quality_options_schema = validate.Schema(
 
 
 class UsherService(object):
+    def __init__(self, session):
+        self.session = session
+
     def _create_url(self, endpoint, **extra_params):
         url = "https://usher.ttvnw.net{0}".format(endpoint)
         params = {
@@ -143,8 +146,8 @@ class UsherService(object):
 
         req = requests.Request("GET", url, params=params)
         # prepare_request is only available in requests 2.0+
-        if hasattr(http, "prepare_request"):
-            req = http.prepare_request(req)
+        if hasattr(self.session.http, "prepare_request"):
+            req = self.session.http.prepare_request(req)
         else:
             req = req.prepare()
 
@@ -159,13 +162,14 @@ class UsherService(object):
 
 
 class TwitchAPI(object):
-    def __init__(self, beta=False, version=3):
+    def __init__(self, session, beta=False, version=3):
         self.oauth_token = None
+        self.session = session
         self.subdomain = beta and "betaapi" or "api"
         self.version = version
 
     def add_cookies(self, cookies):
-        http.parse_cookies(cookies, domain="twitch.tv")
+        self.session.http.parse_cookies(cookies, domain="twitch.tv")
 
     def call(self, path, format="json", schema=None, **extra_params):
         params = dict(as3="t", **extra_params)
@@ -181,10 +185,10 @@ class TwitchAPI(object):
         headers = {'Accept': 'application/vnd.twitchtv.v{0}+json'.format(self.version),
                    'Client-ID': TWITCH_CLIENT_ID}
 
-        res = http.get(url, params=params, headers=headers)
+        res = self.session.http.get(url, params=params, headers=headers)
 
         if format == "json":
-            return http.json(res, schema=schema)
+            return self.session.http.json(res, schema=schema)
         else:
             return res
 
@@ -224,8 +228,8 @@ class TwitchAPI(object):
         return self.call_subdomain("tmi", "/hosts", format="", **params)
 
     def clip_status(self, channel, clip_name, schema):
-        return http.json(self.call_subdomain("clips", "/api/v2/clips/" + clip_name + "/status", format=""),
-                         schema=schema)
+        return self.session.http.json(self.call_subdomain("clips", "/api/v2/clips/" + clip_name + "/status", format=""),
+                                      schema=schema)
 
     # Unsupported/Removed private API calls
 
@@ -315,8 +319,10 @@ class Twitch(Plugin):
             self.video_id = match.get("video_id") or match.get("videos_id")
             self.clip_name = match.get("clip_name")
 
-        self.api = TwitchAPI(beta=self.subdomain == "beta", version=5)
-        self.usher = UsherService()
+        self.api = TwitchAPI(beta=self.subdomain == "beta",
+                             session=self.session,
+                             version=5)
+        self.usher = UsherService(session=self.session)
 
     @property
     def channel(self):
@@ -565,9 +571,10 @@ class Twitch(Plugin):
             elif hosted_channel:
                 self.logger.info("switching to {0}", hosted_channel)
                 if hosted_channel in self._hosted_chain:
-                    self.logger.error(u"A loop of hosted channels has been detected, "
-                                      "cannot find a playable stream. ({0})".format(
-                        u" -> ".join(self._hosted_chain + [hosted_channel])))
+                    self.logger.error(
+                        u"A loop of hosted channels has been detected, "
+                        "cannot find a playable stream. ({0})".format(
+                            u" -> ".join(self._hosted_chain + [hosted_channel])))
                     return {}
                 self.channel = hosted_channel
                 return self._get_hls_streams(stream_type)
diff --git a/src/streamlink/plugins/ustreamtv.py b/src/streamlink/plugins/ustreamtv.py
index 8502ade2..60494ccc 100644
--- a/src/streamlink/plugins/ustreamtv.py
+++ b/src/streamlink/plugins/ustreamtv.py
@@ -8,7 +8,6 @@ import time
 from streamlink import PluginError
 from streamlink.compat import urljoin
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
@@ -42,7 +41,7 @@ class UHSClient(object):
 
     def __init__(self, session, media_id, application, **options):
         self.session = session
-        http.headers.update({"User-Agent": useragents.IPHONE_6})
+        self.session.http.headers.update({"User-Agent": useragents.IPHONE_6})
         self.logger = logging.getLogger("streamlink.plugin.ustream.apiclient")
         self.media_id = media_id
         self.application = application
@@ -92,14 +91,14 @@ class UHSClient(object):
         return "_rpin.{0}".format(randint(0, 1e15))
 
     def send_command(self, schema=None, retries=5, timeout=5.0, **args):
-        res = http.get(self.host,
+        res = self.session.http.get(self.host,
                        params=args,
                        headers={"Referer": self.referrer,
                                 "User-Agent": useragents.IPHONE_6},
                        retries=retries,
                        timeout=timeout,
                        retry_max_backoff=0.5)
-        return http.json(res, schema=schema or self.api_schama)
+        return self.session.http.json(res, schema=schema or self.api_schama)
 
     @property
     def host(self):
@@ -263,7 +262,7 @@ class UStreamTV(Plugin):
 
     def _find_media_id(self):
         self.logger.debug("Searching for media ID on the page")
-        res = http.get(self.url, headers={"User-Agent": useragents.CHROME})
+        res = self.session.http.get(self.url, headers={"User-Agent": useragents.CHROME})
         m = self.media_id_re.search(res.text)
         return m and m.group(1)
 
diff --git a/src/streamlink/plugins/ustvnow.py b/src/streamlink/plugins/ustvnow.py
index 1e0eb913..f02446df 100644
--- a/src/streamlink/plugins/ustvnow.py
+++ b/src/streamlink/plugins/ustvnow.py
@@ -5,7 +5,7 @@ import re
 from collections import OrderedDict
 
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HLSStream
 
@@ -47,7 +47,7 @@ class USTVNow(Plugin):
         return cls._url_re.match(url) is not None
 
     def login(self, username, password):
-        r = http.get(self._signin_url)
+        r = self.session.http.get(self._signin_url)
         csrf = None
 
         for input in itertags(r.text, "input"):
@@ -56,7 +56,7 @@ class USTVNow(Plugin):
 
         log.debug("CSRF: {0}", csrf)
 
-        r = http.post(self._login_url, data={'csrf_ustvnow': csrf,
+        r = self.session.http.post(self._login_url, data={'csrf_ustvnow': csrf,
                                              'signin_email': username,
                                              'signin_password': password,
                                              'signin_remember': '1'})
@@ -71,7 +71,7 @@ class USTVNow(Plugin):
         m = self._url_re.match(self.url)
         scode = m and m.group("scode") or self.get_option("station_code")
 
-        res = http.get(self._guide_url, params=dict(token=token))
+        res = self.session.http.get(self._guide_url, params=dict(token=token))
 
         channels = OrderedDict()
         for t in itertags(res.text, "a"):
@@ -86,14 +86,14 @@ class USTVNow(Plugin):
         if scode in channels:
             log.debug("Finding streams for: {0}", channels.get(scode))
 
-            r = http.get(self._stream_url, params={"scode": scode,
+            r = self.session.http.get(self._stream_url, params={"scode": scode,
                                                    "token": token,
                                                    "br_n": "Firefox",
                                                    "br_v": "52",
                                                    "br_d": "desktop"},
                          headers={"User-Agent": useragents.FIREFOX})
 
-            data = http.json(r)
+            data = self.session.http.json(r)
             return HLSStream.parse_variant_playlist(self.session, data["stream"])
         else:
             log.error("Invalid station-code: {0}", scode)
diff --git a/src/streamlink/plugins/vgtv.py b/src/streamlink/plugins/vgtv.py
index ac44f949..e7ce0c60 100644
--- a/src/streamlink/plugins/vgtv.py
+++ b/src/streamlink/plugins/vgtv.py
@@ -3,7 +3,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream, HTTPStream
 
 # This will have to be set to handle "secure" HDS streams. For now we
@@ -82,7 +82,7 @@ class VGTV(Plugin):
 
         # If we can't, we need to get the VGTV ID from the page content
         else:
-            res = http.get(self.url)
+            res = self.session.http.get(self.url)
             match = _content_id_re.search(res.text)
             if match:
                 video_id = match.group(1)
@@ -92,8 +92,8 @@ class VGTV(Plugin):
 
         # Now fetch video information
         self.logger.debug("Fetching video info for ID {0}", video_id)
-        res = http.get(INFO_URL, params=dict(id=video_id))
-        info = http.json(res, schema=_video_schema)
+        res = self.session.http.get(INFO_URL, params=dict(id=video_id))
+        info = self.session.http.json(res, schema=_video_schema)
 
         streams = {}
 
diff --git a/src/streamlink/plugins/viasat.py b/src/streamlink/plugins/viasat.py
index 1281a8dc..041848e6 100644
--- a/src/streamlink/plugins/viasat.py
+++ b/src/streamlink/plugins/viasat.py
@@ -3,7 +3,7 @@ import re
 from streamlink import NoStreamsError
 from streamlink.exceptions import PluginError
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import StreamMapper, http, validate
+from streamlink.plugin.api import StreamMapper, validate
 from streamlink.stream import HDSStream, HLSStream, RTMPStream
 from streamlink.utils import rtmpparse
 
@@ -63,7 +63,7 @@ class Viasat(Plugin):
         return cls._url_re.match(url)
 
     def _get_swf_url(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         match = _swf_url_re.search(res.text)
         if not match:
             raise PluginError("Unable to find SWF URL in the HTML")
@@ -95,8 +95,8 @@ class Viasat(Plugin):
         return name, RTMPStream(self.session, params)
 
     def _extract_streams(self, stream_id):
-        res = http.get(STREAM_API_URL.format(stream_id), raise_for_status=False)
-        stream_info = http.json(res, schema=_stream_schema)
+        res = self.session.http.get(STREAM_API_URL.format(stream_id), raise_for_status=False)
+        stream_info = self.session.http.json(res, schema=_stream_schema)
 
         if stream_info.get("msg"):
             # error message
@@ -135,7 +135,7 @@ class Viasat(Plugin):
         stream_id = match.group("stream_id")
 
         if not stream_id:
-            text = http.get(self.url).text
+            text = self.session.http.get(self.url).text
             stream_id = self._get_stream_id(text)
 
             if not stream_id:
diff --git a/src/streamlink/plugins/vidio.py b/src/streamlink/plugins/vidio.py
index 674a58b7..8dd5a69d 100644
--- a/src/streamlink/plugins/vidio.py
+++ b/src/streamlink/plugins/vidio.py
@@ -6,7 +6,7 @@ Plugin for vidio.com
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -27,20 +27,20 @@ class Vidio(Plugin):
         return cls._url_re.match(url)
 
     def get_csrf_tokens(self):
-        return http.get(self.csrf_tokens_url,
+        return self.session.http.get(self.csrf_tokens_url,
                         schema=self.token_schema)
 
     def get_url_tokens(self, stream_id):
         self.logger.debug("Getting stream tokens")
         csrf_token = self.get_csrf_tokens()
-        return http.post(self.tokens_url.format(id=stream_id),
+        return self.session.http.post(self.tokens_url.format(id=stream_id),
                          files={"authenticity_token": (None, csrf_token)},
                          headers={"User-Agent": useragents.CHROME,
                                   "Referer": self.url},
                          schema=self.token_schema)
 
     def _get_streams(self):
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
 
         plmatch = self._playlist_re.search(res.text)
         idmatch = self._data_id_re.search(res.text)
diff --git a/src/streamlink/plugins/vinhlongtv.py b/src/streamlink/plugins/vinhlongtv.py
index 9e6b5b66..eba00cc5 100644
--- a/src/streamlink/plugins/vinhlongtv.py
+++ b/src/streamlink/plugins/vinhlongtv.py
@@ -2,7 +2,7 @@ import logging
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream
 
 log = logging.getLogger(__name__)
@@ -27,12 +27,12 @@ class VinhLongTV(Plugin):
         return cls._url_re.match(url) is not None
 
     def _get_streams(self):
-        http.headers.update({'User-Agent': useragents.FIREFOX})
+        self.session.http.headers.update({'User-Agent': useragents.FIREFOX})
 
         channel = self._url_re.match(self.url).group('channel')
 
-        res = http.get(self.api_url.format(channel))
-        hls_url = http.json(res, schema=self._data_schema)
+        res = self.session.http.get(self.api_url.format(channel))
+        hls_url = self.session.http.json(res, schema=self._data_schema)
         log.debug('URL={0}'.format(hls_url))
 
         streams = HLSStream.parse_variant_playlist(self.session, hls_url)
diff --git a/src/streamlink/plugins/vk.py b/src/streamlink/plugins/vk.py
index 085e2e2d..d399363a 100644
--- a/src/streamlink/plugins/vk.py
+++ b/src/streamlink/plugins/vk.py
@@ -4,7 +4,7 @@ import re
 
 from streamlink.compat import urlparse, unquote
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.plugin.api.utils import itertags
 from streamlink.stream import HTTPStream, HLSStream
 from streamlink.utils import update_scheme
@@ -52,7 +52,7 @@ class VK(Plugin):
         Find the streams for vk.com
         :return:
         """
-        http.headers.update({'User-Agent': useragents.IPHONE_6})
+        self.session.http.headers.update({'User-Agent': useragents.IPHONE_6})
 
         # If this is a 'videos' catalog URL
         # with an video ID in the GET request, get that instead
@@ -71,7 +71,7 @@ class VK(Plugin):
             'al': '1',
             'video': video_id,
         }
-        res = http.post(self.API_URL, params=params)
+        res = self.session.http.post(self.API_URL, params=params)
 
         for _i in itertags(res.text, 'iframe'):
             if _i.attributes.get('src'):
diff --git a/src/streamlink/plugins/webcast_india_gov.py b/src/streamlink/plugins/webcast_india_gov.py
index 92b8ec5f..c7aafcda 100644
--- a/src/streamlink/plugins/webcast_india_gov.py
+++ b/src/streamlink/plugins/webcast_india_gov.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
 
@@ -15,12 +15,12 @@ class WebcastIndiaGov(Plugin):
     def _get_streams(self):
         try:
             url_content = ""
-            http.headers = {'User-Agent': useragents.ANDROID}
+            self.session.http.headers = {'User-Agent': useragents.ANDROID}
             if "#channel" in self.url.lower():
                 requested_channel = self.url.lower()[self.url.lower().index('#channel') + 8:]
-                url_content = http.get('http://webcast.gov.in/mobilevideo.asp?id=div' + requested_channel).text
+                url_content = self.session.http.get('http://webcast.gov.in/mobilevideo.asp?id=div' + requested_channel).text
             else:
-                url_content = http.get(self.url).text
+                url_content = self.session.http.get(self.url).text
             hls_url = url_content[: url_content.rindex('master.m3u8') + 11]
             hls_url = hls_url[hls_url.rindex('"') + 1:]
             return HLSStream.parse_variant_playlist(self.session, hls_url)
diff --git a/src/streamlink/plugins/webtv.py b/src/streamlink/plugins/webtv.py
index b0362b44..6afa6e4b 100644
--- a/src/streamlink/plugins/webtv.py
+++ b/src/streamlink/plugins/webtv.py
@@ -7,7 +7,6 @@ import binascii
 from Crypto.Cipher import AES
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json, update_scheme
@@ -53,7 +52,7 @@ class WebTV(Plugin):
         :return:
         """
         headers = {}
-        res = http.get(self.url, headers=headers)
+        res = self.session.http.get(self.url, headers=headers)
         headers["Referer"] = self.url
 
         sources = self._sources_re.findall(res.text)
diff --git a/src/streamlink/plugins/weeb.py b/src/streamlink/plugins/weeb.py
index 40ff58e7..ae5bb194 100644
--- a/src/streamlink/plugins/weeb.py
+++ b/src/streamlink/plugins/weeb.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin, PluginError
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.plugin.api.utils import parse_query
 from streamlink.stream import RTMPStream
 
@@ -67,7 +67,7 @@ class Weeb(Plugin):
             "firstConnect": 1,
             "ip": "NaN"
         }
-        res = http.post(API_URL, data=form, headers=HEADERS)
+        res = self.session.http.post(API_URL, data=form, headers=HEADERS)
         params = parse_query(res.text, schema=_schema)
 
         if params["status"] <= 0:
diff --git a/src/streamlink/plugins/welt.py b/src/streamlink/plugins/welt.py
index bdc0a90b..a159b048 100644
--- a/src/streamlink/plugins/welt.py
+++ b/src/streamlink/plugins/welt.py
@@ -2,7 +2,7 @@ import re
 
 from streamlink.compat import quote
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, useragents, validate
+from streamlink.plugin.api import useragents, validate
 from streamlink.stream import HLSStream
 from streamlink.utils import parse_json
 
@@ -72,12 +72,12 @@ class Welt(Plugin):
 
     def _get_streams(self):
         headers = {"User-Agent": useragents.CHROME}
-        hls_url = http.get(self.url, headers=headers, schema=self._schema)
+        hls_url = self.session.http.get(self.url, headers=headers, schema=self._schema)
         headers["Referer"] = self.url
 
         if self.isVod:
             url = self._url_vod.format(quote(hls_url, safe=""))
-            hls_url = http.get(url, headers=headers, schema=self._schema_vod)
+            hls_url = self.session.http.get(url, headers=headers, schema=self._schema_vod)
 
         return HLSStream.parse_variant_playlist(self.session, hls_url, headers=headers)
 
diff --git a/src/streamlink/plugins/wwenetwork.py b/src/streamlink/plugins/wwenetwork.py
index 2d1fe046..6200c462 100644
--- a/src/streamlink/plugins/wwenetwork.py
+++ b/src/streamlink/plugins/wwenetwork.py
@@ -7,7 +7,6 @@ import time
 from streamlink import PluginError
 from streamlink.cache import Cache
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.compat import urlparse, parse_qsl
@@ -66,7 +65,7 @@ class WWENetwork(Plugin):
 
     def __init__(self, url):
         super(WWENetwork, self).__init__(url)
-        http.headers.update({"User-Agent": useragents.CHROME})
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
         self._session_attributes = Cache(filename="plugin-cache.json", key_prefix="wwenetwork:attributes")
         self._session_key = self.cache.get("session_key")
         self._authed = self._session_attributes.get("ipid") and self._session_attributes.get("fprt")
@@ -78,9 +77,9 @@ class WWENetwork(Plugin):
     def login(self, email, password):
         self.logger.debug("Attempting login as {0}", email)
         # sets some required cookies to login
-        http.get(self.login_page_url)
+        self.session.http.get(self.login_page_url)
         # login
-        res = http.post(self.login_url, data=dict(registrationAction='identify',
+        res = self.session.http.post(self.login_url, data=dict(registrationAction='identify',
                                                   emailAddress=email,
                                                   password=password,
                                                   submitButton=""),
@@ -97,7 +96,7 @@ class WWENetwork(Plugin):
     def _update_session_attribute(self, key, value):
         if value:
             self._session_attributes.set(key, value, expires=3600 * 1.5)  # 1h30m expiry
-            http.cookies.set(key, value)
+            self.session.http.cookies.set(key, value)
 
     @property
     def session_key(self):
@@ -125,12 +124,12 @@ class WWENetwork(Plugin):
         if self.session_key:
             params["sessionKey"] = self.session_key
         url = self.api_url.format(id=content_id)
-        res = http.get(url, params=params)
-        return http.xml(res, ignore_ns=True, schema=self._info_schema)
+        res = self.session.http.get(url, params=params)
+        return self.session.http.xml(res, ignore_ns=True, schema=self._info_schema)
 
     def _get_content_id(self):
         #  check the page to find the contentId
-        res = http.get(self.url)
+        res = self.session.http.get(self.url)
         m = self.content_id_re.search(res.text)
         if m:
             return m.group(1)
diff --git a/src/streamlink/plugins/younow.py b/src/streamlink/plugins/younow.py
index ace28108..1ddd3a95 100644
--- a/src/streamlink/plugins/younow.py
+++ b/src/streamlink/plugins/younow.py
@@ -3,7 +3,6 @@
 import re
 
 from streamlink.plugin import Plugin, PluginError
-from streamlink.plugin.api import http
 from streamlink.stream import RTMPStream
 
 jsonapi = "https://api.younow.com/php/api/broadcast/info/curId=0/user="
@@ -14,8 +13,8 @@ _url_re = re.compile(r"http(s)?://(\w+.)?younow.com/(?P<channel>[^/&?]+)")
 
 def getStreamURL(channel):
     url = jsonapi + channel
-    res = http.get(url)
-    streamerinfo = http.json(res)
+    res = self.session.http.get(url)
+    streamerinfo = self.session.http.json(res)
     # print(streamerinfo)
 
     if not any("media" in s for s in streamerinfo):
diff --git a/src/streamlink/plugins/youtube.py b/src/streamlink/plugins/youtube.py
index 6fd21454..fa0612c8 100644
--- a/src/streamlink/plugins/youtube.py
+++ b/src/streamlink/plugins/youtube.py
@@ -6,7 +6,7 @@ import re
 
 from streamlink.compat import parse_qsl, is_py2
 from streamlink.plugin import Plugin, PluginError, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, validate, useragents
+from streamlink.plugin.api import validate, useragents
 from streamlink.plugin.api.utils import parse_query, itertags
 from streamlink.stream import HTTPStream, HLSStream
 from streamlink.stream.ffmpegmux import MuxedStream
@@ -217,7 +217,7 @@ class YouTube(Plugin):
             log.debug("Video ID from URL")
             return m.group("video_id")
 
-        res = http.get(url)
+        res = self.session.http.get(url)
         datam = _ytdata_re.search(res.text)
         if datam:
             data = parse_json(datam.group(1))
@@ -249,7 +249,7 @@ class YouTube(Plugin):
             params = {"video_id": video_id}
             params.update(_params)
 
-            res = http.get(self._video_info_url, params=params)
+            res = self.session.http.get(self._video_info_url, params=params)
             info_parsed = parse_query(res.content if is_py2 else res.text, name="config", schema=_config_schema)
             if info_parsed.get("status") == "fail":
                 log.debug("get_video_info - {0}: {1}".format(
@@ -262,7 +262,7 @@ class YouTube(Plugin):
         return info_parsed
 
     def _get_streams(self):
-        http.headers.update({'User-Agent': useragents.CHROME})
+        self.session.http.headers.update({'User-Agent': useragents.CHROME})
         is_live = False
 
         video_id = self._find_video_id(self.url)
diff --git a/src/streamlink/plugins/yupptv.py b/src/streamlink/plugins/yupptv.py
index e9261b7b..3d2c2304 100644
--- a/src/streamlink/plugins/yupptv.py
+++ b/src/streamlink/plugins/yupptv.py
@@ -3,7 +3,7 @@ import re
 
 from streamlink import PluginError
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
-from streamlink.plugin.api import http, useragents
+from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
 
@@ -43,18 +43,18 @@ class YuppTV(Plugin):
             log.error("Failed to login to YuppTV")
             raise PluginError("cannot login")
 
-        res = http.post(self._login_url, data=dict(user=username, password=password, isMobile=0), headers={"Referer": self._signin_url})
-        data = http.json(res)
+        res = self.session.http.post(self._login_url, data=dict(user=username, password=password, isMobile=0), headers={"Referer": self._signin_url})
+        data = self.session.http.json(res)
         resp = data['Response']
         if resp["tempBoxid"]:
             # log out on other device
             log.info("Logging out on other device: {0}".format(resp["tempBoxid"]))
-            _ = http.get(self._box_logout, params=dict(boxId=resp["tempBoxid"]))
+            _ = self.session.http.get(self._box_logout, params=dict(boxId=resp["tempBoxid"]))
             return self.login(username, password, depth-1)
         return resp['errorCode'], resp['statusmsg']
 
     def _get_streams(self):
-        http.headers.update({"User-Agent": useragents.CHROME})
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
 
         if self.get_option("email") and self.get_option("password"):
             error_code, error_msg = self.login(self.get_option("email"), self.get_option("password"))
@@ -63,7 +63,7 @@ class YuppTV(Plugin):
             else:
                 log.error("Failed to login: {1} (code: {0})".format(error_code, error_msg))
 
-        page = http.get(self.url)
+        page = self.session.http.get(self.url)
         match = self._m3u8_re.search(page.text)
         if match:
             stream_url = match.group(1)
diff --git a/src/streamlink/plugins/zattoo.py b/src/streamlink/plugins/zattoo.py
index 297a4066..9a8c4a01 100644
--- a/src/streamlink/plugins/zattoo.py
+++ b/src/streamlink/plugins/zattoo.py
@@ -8,7 +8,6 @@ from streamlink import PluginError
 from streamlink.cache import Cache
 from streamlink.plugin import Plugin
 from streamlink.plugin import PluginArguments, PluginArgument
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.plugin.api import validate
 from streamlink.stream import DASHStream, HLSStream
@@ -151,8 +150,8 @@ class Zattoo(Plugin):
         log.debug('_hello ...')
 
         # a new session is required for the app_token
-        http.cookies = cookiejar_from_dict({})
-        res = http.get(self.base_url)
+        self.session.http.cookies = cookiejar_from_dict({})
+        res = self.session.http.get(self.base_url)
         match = self._app_token_re.search(res.text)
 
         app_token = match.group(1)
@@ -171,7 +170,7 @@ class Zattoo(Plugin):
             'lang': 'en',
             'format': 'json'
         }
-        res = http.post(hello_url, headers=self.headers, data=params)
+        res = self.session.http.post(hello_url, headers=self.headers, data=params)
 
     def _login(self, email, password):
         log.debug('_login ... Attempting login as {0}'.format(email))
@@ -184,14 +183,14 @@ class Zattoo(Plugin):
         }
 
         try:
-            res = http.post(login_url, headers=self.headers, data=params)
+            res = self.session.http.post(login_url, headers=self.headers, data=params)
         except Exception as e:
             if '400 Client Error' in str(e):
                 raise PluginError(
                     'Failed to login, check your username/password')
             raise e
 
-        data = http.json(res)
+        data = self.session.http.json(res)
         self._authed = data['success']
         log.debug('New Session Data')
         self.save_cookies(default_expires=self.TIME_SESSION)
@@ -234,7 +233,7 @@ class Zattoo(Plugin):
             params.update(params_stream_type)
 
             try:
-                res = http.post(watch_url, headers=self.headers, data=params)
+                res = self.session.http.post(watch_url, headers=self.headers, data=params)
             except Exception as e:
                 if '404 Client Error' in str(e):
                     log.error('Unfortunately streaming is not permitted in '
@@ -250,7 +249,7 @@ class Zattoo(Plugin):
                     log.error(str(e))
                 return
 
-            data = http.json(res)
+            data = self.session.http.json(res)
             log.debug('Found data for {0}'.format(stream_type))
             if data['success'] and stream_type in ['hls', 'hls5']:
                 for url in data['stream']['watch_urls']:
@@ -271,13 +270,13 @@ class Zattoo(Plugin):
             self._session_attributes.get('power_guide_hash'))
 
         try:
-            res = http.get(channels_url, headers=self.headers)
+            res = self.session.http.get(channels_url, headers=self.headers)
         except Exception:
             log.debug('Force session reset for _get_params_cid')
             self.reset_session()
             return False
 
-        data = http.json(res, schema=self._channels_schema)
+        data = self.session.http.json(res, schema=self._channels_schema)
 
         c_list = []
         for d in data:
@@ -317,8 +316,8 @@ class Zattoo(Plugin):
         elif (self._authed and not self._session_control):
             # check every two hours, if the session is actually valid
             log.debug('Session control for {0}'.format(self.domain))
-            res = http.get(self.API_SESSION.format(self.base_url))
-            res = http.json(res, schema=self._session_schema)
+            res = self.session.http.get(self.API_SESSION.format(self.base_url))
+            res = self.session.http.json(res, schema=self._session_schema)
             if res['loggedin']:
                 self._session_attributes.set(
                     'session_control', True, expires=self.TIME_CONTROL)
diff --git a/src/streamlink/plugins/zdf_mediathek.py b/src/streamlink/plugins/zdf_mediathek.py
index fb8b6eae..4db51ddb 100644
--- a/src/streamlink/plugins/zdf_mediathek.py
+++ b/src/streamlink/plugins/zdf_mediathek.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HDSStream, HLSStream
 from streamlink.utils import parse_json
 
@@ -123,7 +123,7 @@ class zdf_mediathek(Plugin):
         return qualities
 
     def _get_streams(self):
-        zdf_json = http.get(self.url, schema=_api_schema)
+        zdf_json = self.session.http.get(self.url, schema=_api_schema)
         if zdf_json is None:
             return
 
@@ -132,14 +132,14 @@ class zdf_mediathek(Plugin):
             "Referer": self.url
         }
 
-        res = http.get(zdf_json['content'], headers=headers)
-        document = http.json(res, schema=_documents_schema)
+        res = self.session.http.get(zdf_json['content'], headers=headers)
+        document = self.session.http.json(res, schema=_documents_schema)
 
         stream_request_url = document["mainVideoContent"]["http://zdf.de/rels/target"]["http://zdf.de/rels/streams/ptmd"]
         stream_request_url = API_URL + stream_request_url
 
-        res = http.get(stream_request_url, headers=headers)
-        res = http.json(res, schema=_schema)
+        res = self.session.http.get(stream_request_url, headers=headers)
+        res = self.session.http.json(res, schema=_schema)
 
         streams = {}
         for format_ in self._extract_streams(res):
diff --git a/src/streamlink/plugins/zengatv.py b/src/streamlink/plugins/zengatv.py
index 24c79a36..60f857e2 100644
--- a/src/streamlink/plugins/zengatv.py
+++ b/src/streamlink/plugins/zengatv.py
@@ -1,7 +1,6 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
 
@@ -25,7 +24,7 @@ class ZengaTV(Plugin):
             "Referer": self.url,
         }
 
-        res = http.get(self.url, headers=headers)
+        res = self.session.http.get(self.url, headers=headers)
         for id_re in (self._id_re, self._id_2_re):
             m = id_re.search(res.text)
             if not m:
@@ -39,7 +38,7 @@ class ZengaTV(Plugin):
         dvr_id = m.group("id")
         self.logger.debug("Found video id: {0}".format(dvr_id))
         data = {"feed": "hd", "dvrId": dvr_id}
-        res = http.post(self.api_url, headers=headers, data=data)
+        res = self.session.http.post(self.api_url, headers=headers, data=data)
         if res.status_code == 200:
             for s in HLSStream.parse_variant_playlist(self.session, res.text, headers=headers).items():
                 yield s
diff --git a/src/streamlink/plugins/zhanqi.py b/src/streamlink/plugins/zhanqi.py
index 80829518..3e804e5c 100644
--- a/src/streamlink/plugins/zhanqi.py
+++ b/src/streamlink/plugins/zhanqi.py
@@ -1,7 +1,7 @@
 import re
 
 from streamlink.plugin import Plugin
-from streamlink.plugin.api import http, validate
+from streamlink.plugin.api import validate
 from streamlink.stream import HTTPStream, HLSStream
 
 API_URL = "https://www.zhanqi.tv/api/static/v2.1/room/domain/{0}.json"
@@ -37,8 +37,8 @@ class Zhanqitv(Plugin):
         match = _url_re.match(self.url)
         channel = match.group("channel")
 
-        res = http.get(API_URL.format(channel))
-        room = http.json(res, schema=_room_schema)
+        res = self.session.http.get(API_URL.format(channel))
+        room = self.session.http.json(res, schema=_room_schema)
         if not room:
             self.logger.info("Not a valid room url.")
             return
diff --git a/src/streamlink/stream/dash.py b/src/streamlink/stream/dash.py
index e202e53b..1d1c5b65 100644
--- a/src/streamlink/stream/dash.py
+++ b/src/streamlink/stream/dash.py
@@ -11,6 +11,7 @@ from streamlink.stream.stream import Stream
 from streamlink.stream.dash_manifest import MPD, sleeper, sleep_until, utc, freeze_timeline
 from streamlink.stream.ffmpegmux import FFMPEGMuxer
 from streamlink.stream.segmented import SegmentedStreamReader, SegmentedStreamWorker, SegmentedStreamWriter
+from streamlink.utils.l10n import Language
 
 log = logging.getLogger(__name__)
 
@@ -196,6 +197,31 @@ class DASHStream(Stream):
         if not audio:
             audio = [None]
 
+        locale = session.localization
+        locale_lang = locale.language
+        lang = None
+        available_languages = set()
+
+        # if the locale is explicitly set, prefer that language over others
+        for aud in audio:
+            if aud and aud.lang:
+                available_languages.add(aud.lang)
+                try:
+                    if locale.explicit and aud.lang and Language.get(aud.lang) == locale_lang:
+                        lang = aud.lang
+                except LookupError:
+                    continue
+
+        if not lang:
+            # filter by the first language that appears
+            lang = audio[0] and audio[0].lang
+
+        log.debug("Available languages for DASH audio streams: {0} (using: {1})".format(", ".join(available_languages) or "NONE", lang or "n/a"))
+
+        # if the language is given by the stream, filter out other languages that do not match
+        if len(available_languages) > 1:
+            audio = list(filter(lambda a: a.lang is None or a.lang == lang, audio))
+
         for vid, aud in itertools.product(video, audio):
             stream = DASHStream(session, mpd, vid, aud, **args)
             stream_name = []
diff --git a/src/streamlink/stream/hls.py b/src/streamlink/stream/hls.py
index 0fe12ad5..87890f4f 100644
--- a/src/streamlink/stream/hls.py
+++ b/src/streamlink/stream/hls.py
@@ -295,7 +295,7 @@ class MuxedHLSStream(MuxedStream):
 
     def __init__(self, session, video, audio, force_restart=False, ffmpeg_options=None, **args):
         tracks = [video]
-        maps = ["0:v"]
+        maps = ["0:v?", "0:a?"]
         if audio:
             if isinstance(audio, list):
                 tracks.extend(audio)
diff --git a/src/streamlink/stream/hls_playlist.py b/src/streamlink/stream/hls_playlist.py
index 7f027218..4ed7f568 100644
--- a/src/streamlink/stream/hls_playlist.py
+++ b/src/streamlink/stream/hls_playlist.py
@@ -38,9 +38,6 @@ Resolution = namedtuple("Resolution", "width height")
 Segment = namedtuple("Segment", "uri duration title key discontinuity "
                                 "byterange date map")
 
-ATTRIBUTE_REGEX = (r"([A-Z\-]+)=(\d+\.\d+|0x[0-9A-z]+|\d+x\d+|\d+|"
-                   r"\"(.+?)\"|[0-9A-z\-]+)")
-
 
 class M3U8(object):
     def __init__(self):
@@ -62,6 +59,12 @@ class M3U8(object):
 
 
 class M3U8Parser(object):
+    _extinf_re = re.compile(r"(?P<duration>\d+(\.\d+)?)(,(?P<title>.+))?")
+    _attr_re = re.compile(r"([A-Z\-]+)=(\d+\.\d+|0x[0-9A-z]+|\d+x\d+|\d+|\"(.+?)\"|[0-9A-z\-]+)")
+    _range_re = re.compile(r"(?P<range>\d+)(@(?P<offset>.+))?")
+    _tag_re = re.compile(r"#(?P<tag>[\w-]+)(:(?P<value>.+))?")
+    _res_re = re.compile(r"(\d+)x(\d+)")
+
     def __init__(self, base_uri=None):
         self.base_uri = base_uri
 
@@ -91,7 +94,7 @@ class M3U8Parser(object):
                               streaminf.get("SUBTITLES"))
 
     def split_tag(self, line):
-        match = re.match("#(?P<tag>[\w-]+)(:(?P<value>.+))?", line)
+        match = self._tag_re.match(line)
 
         if match:
             return match.group("tag"), (match.group("value") or "").strip()
@@ -102,7 +105,7 @@ class M3U8Parser(object):
         def map_attribute(key, value, quoted):
             return (key, quoted or value)
 
-        attr = re.findall(ATTRIBUTE_REGEX, value)
+        attr = self._attr_re.findall(value)
 
         return dict(starmap(map_attribute, attr))
 
@@ -110,14 +113,14 @@ class M3U8Parser(object):
         return value == "YES"
 
     def parse_byterange(self, value):
-        match = re.match("(?P<range>\d+)(@(?P<offset>.+))?", value)
+        match = self._range_re.match(value)
 
         if match:
             return ByteRange(int(match.group("range")),
                              int(match.group("offset") or 0))
 
     def parse_extinf(self, value):
-        match = re.match("(?P<duration>\d+(\.\d+)?)(,(?P<title>.+))?", value)
+        match = self._extinf_re.match(value)
         if match:
             return float(match.group("duration")), match.group("title")
         return (0, None)
@@ -130,7 +133,7 @@ class M3U8Parser(object):
         return unhexlify(value)
 
     def parse_resolution(self, value):
-        match = re.match("(\d+)x(\d+)", value)
+        match = self._res_re.match(value)
 
         if match:
             width, height = int(match.group(1)), int(match.group(2))
@@ -147,10 +150,7 @@ class M3U8Parser(object):
 
         return value
 
-    def parse_line(self, lineno, line):
-        if lineno == 0 and not line.startswith("#EXTM3U"):
-            raise ValueError("Missing #EXTM3U header")
-
+    def parse_line(self, line):
         if not line.startswith("#"):
             if self.state.pop("expect_segment", None):
                 byterange = self.state.pop("byterange", None)
@@ -238,8 +238,18 @@ class M3U8Parser(object):
         self.state = {}
         self.m3u8 = M3U8()
 
-        for lineno, line in enumerate(filter(bool, data.splitlines())):
-            self.parse_line(lineno, line)
+        lines = iter(filter(bool, data.splitlines()))
+        try:
+            line = next(lines)
+        except StopIteration:
+            return self.m3u8
+        else:
+            if not line.startswith("#EXTM3U"):
+                raise ValueError("Missing #EXTM3U header")
+
+        parse_line = self.parse_line
+        for line in lines:
+            parse_line(line)
 
         # Associate Media entries with each Playlist
         for playlist in self.m3u8.playlists:


Test patch:
diff --git a/tests/plugins/test_garena.py b/tests/plugins/test_garena.py
index 9a00d56b..197698a5 100644
--- a/tests/plugins/test_garena.py
+++ b/tests/plugins/test_garena.py
@@ -2,8 +2,9 @@ import json
 import unittest
 
 from streamlink import Streamlink
+from streamlink.plugin.api import HTTPSession
 
-from tests.mock import patch, Mock
+from tests.mock import patch, Mock, MagicMock
 
 from streamlink.plugins.garena import Garena
 
@@ -11,6 +12,8 @@ from streamlink.plugins.garena import Garena
 class TestPluginGarena(unittest.TestCase):
     def setUp(self):
         self.session = Streamlink()
+        self.session.http = MagicMock(HTTPSession)
+        self.session.http.headers = {}
 
     def test_can_handle_url(self):
         # should match
@@ -21,8 +24,7 @@ class TestPluginGarena(unittest.TestCase):
         self.assertFalse(Garena.can_handle_url("http://local.local/"))
         self.assertFalse(Garena.can_handle_url("http://localhost.localhost/"))
 
-    @patch('streamlink.plugins.garena.http')
-    def test_post_api_info(self, mock_http):
+    def test_post_api_info(self):
         API_INFO = Garena.API_INFO
         schema = Garena._info_schema
 
@@ -35,21 +37,21 @@ class TestPluginGarena(unittest.TestCase):
 
         api_resp = Mock()
         api_resp.text = json.dumps(api_data)
-        mock_http.post.return_value = api_resp
-        mock_http.json.return_value = api_data
+        self.session.http.post.return_value = api_resp
+        self.session.http.json.return_value = api_data
 
         payload = {"alias": "LOLTW"}
 
+        Garena.bind(self.session, "test.garena")
         plugin = Garena("https://garena.live/LOLTW")
 
         info_data = plugin._post_api(API_INFO, payload, schema)
 
         self.assertEqual(info_data["channel_id"], 358220)
 
-        mock_http.post.assert_called_with(API_INFO, json=dict(alias="LOLTW"))
+        self.session.http.post.assert_called_with(API_INFO, json=dict(alias="LOLTW"))
 
-    @patch('streamlink.plugins.garena.http')
-    def test_post_api_stream(self, mock_http):
+    def test_post_api_stream(self):
         API_STREAM = Garena.API_STREAM
         schema = Garena._stream_schema
 
@@ -69,15 +71,16 @@ class TestPluginGarena(unittest.TestCase):
 
         api_resp = Mock()
         api_resp.text = json.dumps(api_data)
-        mock_http.post.return_value = api_resp
-        mock_http.json.return_value = api_data
+        self.session.http.post.return_value = api_resp
+        self.session.http.json.return_value = api_data
 
         payload = {"channel_id": 358220}
 
+        Garena.bind(self.session, "test.garena")
         plugin = Garena("https://garena.live/358220")
 
         stream_data = plugin._post_api(API_STREAM, payload, schema)
 
         self.assertEqual(stream_data["streams"], api_data["reply"]["streams"])
 
-        mock_http.post.assert_called_with(API_STREAM, json=dict(channel_id=358220))
+        self.session.http.post.assert_called_with(API_STREAM, json=dict(channel_id=358220))
diff --git a/tests/plugins/test_tvplayer.py b/tests/plugins/test_tvplayer.py
index 7ac48b86..8b010122 100644
--- a/tests/plugins/test_tvplayer.py
+++ b/tests/plugins/test_tvplayer.py
@@ -1,6 +1,7 @@
 import unittest
 
 from streamlink import Streamlink
+from streamlink.plugin.api import HTTPSession
 from streamlink.plugins.tvplayer import TVPlayer
 from streamlink.stream import HLSStream
 from tests.mock import patch, Mock, ANY, MagicMock, call
@@ -9,6 +10,8 @@ from tests.mock import patch, Mock, ANY, MagicMock, call
 class TestPluginTVPlayer(unittest.TestCase):
     def setUp(self):
         self.session = Streamlink()
+        self.session.http = MagicMock(HTTPSession)
+        self.session.http.headers = {}
 
     def test_can_handle_url(self):
         # should match
@@ -27,9 +30,8 @@ class TestPluginTVPlayer(unittest.TestCase):
         self.assertFalse(TVPlayer.can_handle_url("http://www.youtube.com/"))
 
     @patch('streamlink.plugins.tvplayer.TVPlayer._get_stream_data')
-    @patch('streamlink.plugins.tvplayer.http')
     @patch('streamlink.plugins.tvplayer.HLSStream')
-    def test_get_streams(self, hlsstream, mock_http, mock_get_stream_data):
+    def test_get_streams(self, hlsstream, mock_get_stream_data):
         mock_get_stream_data.return_value = {
             "stream": "http://test.se/stream1"
         }
@@ -47,7 +49,7 @@ class TestPluginTVPlayer(unittest.TestCase):
                     <div class="row visible-xs visible-sm">
         """
 
-        mock_http.get.return_value = page_resp
+        self.session.http.get.return_value = page_resp
         hlsstream.parse_variant_playlist.return_value = {"test": HLSStream(self.session, "http://test.se/stream1")}
 
         TVPlayer.bind(self.session, "test.tvplayer")
@@ -58,20 +60,19 @@ class TestPluginTVPlayer(unittest.TestCase):
         self.assertTrue("test" in streams)
 
         # test the url is used correctly
-        mock_http.get.assert_called_with("http://tvplayer.com/watch/dave")
+        self.session.http.get.assert_called_with("http://tvplayer.com/watch/dave")
         # test that the correct API call is made
         mock_get_stream_data.assert_called_with(resource="bbcone", channel_id="89", token="1324567894561268987948596154656418448489159")
         # test that the correct URL is used for the HLSStream
         hlsstream.parse_variant_playlist.assert_called_with(ANY, "http://test.se/stream1")
 
-    @patch('streamlink.plugins.tvplayer.http')
-    def test_get_invalid_page(self, mock_http):
+    def test_get_invalid_page(self):
         page_resp = Mock()
         page_resp.text = u"""
         var validate = "foo";
         var resourceId = "1234";
         """
-        mock_http.get.return_value = page_resp
+        self.session.http.get.return_value = page_resp
 
         TVPlayer.bind(self.session, "test.tvplayer")
         plugin = TVPlayer("http://tvplayer.com/watch/dave")
@@ -82,7 +83,7 @@ class TestPluginTVPlayer(unittest.TestCase):
 
         # test the url is used correctly
 
-        mock_http.get.assert_called_with("http://tvplayer.com/watch/dave")
+        self.session.http.get.assert_called_with("http://tvplayer.com/watch/dave")
 
     def test_arguments(self):
         from streamlink_cli.main import setup_plugin_args
diff --git a/tests/streams/test_dash.py b/tests/streams/test_dash.py
index 807b8a18..cf406185 100644
--- a/tests/streams/test_dash.py
+++ b/tests/streams/test_dash.py
@@ -1,7 +1,4 @@
 import unittest
-import unittest
-from streamlink.stream.dash import DASHStreamWorker
-from tests.mock import MagicMock, patch, ANY, Mock, call
 
 from streamlink import PluginError
 from streamlink.stream import *
@@ -41,8 +38,8 @@ class TestDASHStream(unittest.TestCase):
             Mock(adaptationSets=[
                 Mock(contentProtection=None,
                      representations=[
-                         Mock(id=1, mimeType="audio/mp4", bandwidth=128.0),
-                         Mock(id=2, mimeType="audio/mp4", bandwidth=256.0)
+                         Mock(id=1, mimeType="audio/mp4", bandwidth=128.0, lang='en'),
+                         Mock(id=2, mimeType="audio/mp4", bandwidth=256.0, lang='en')
                      ])
             ])
         ])
@@ -63,7 +60,7 @@ class TestDASHStream(unittest.TestCase):
                      representations=[
                          Mock(id=1, mimeType="video/mp4", height=720),
                          Mock(id=2, mimeType="video/mp4", height=1080),
-                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0)
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='en')
                      ])
             ])
         ])
@@ -84,8 +81,8 @@ class TestDASHStream(unittest.TestCase):
                      representations=[
                          Mock(id=1, mimeType="video/mp4", height=720),
                          Mock(id=2, mimeType="video/mp4", height=1080),
-                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0),
-                         Mock(id=4, mimeType="audio/aac", bandwidth=256.0)
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='en'),
+                         Mock(id=4, mimeType="audio/aac", bandwidth=256.0, lang='en')
                      ])
             ])
         ])
@@ -98,6 +95,108 @@ class TestDASHStream(unittest.TestCase):
             sorted(["720p+a128k", "1080p+a128k", "720p+a256k", "1080p+a256k"])
         )
 
+    @patch('streamlink.stream.dash.MPD')
+    def test_parse_manifest_audio_multi_lang(self, mpdClass):
+        mpd = mpdClass.return_value = Mock(periods=[
+            Mock(adaptationSets=[
+                Mock(contentProtection=None,
+                     representations=[
+                         Mock(id=1, mimeType="video/mp4", height=720),
+                         Mock(id=2, mimeType="video/mp4", height=1080),
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='en'),
+                         Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang='es')
+                     ])
+            ])
+        ])
+
+        streams = DASHStream.parse_manifest(self.session, self.test_url)
+        mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
+
+        self.assertSequenceEqual(
+            sorted(list(streams.keys())),
+            sorted(["720p", "1080p"])
+        )
+
+        self.assertEqual(streams["720p"].audio_representation.lang, "en")
+        self.assertEqual(streams["1080p"].audio_representation.lang, "en")
+
+    @patch('streamlink.stream.dash.MPD')
+    def test_parse_manifest_audio_multi_lang_alpha3(self, mpdClass):
+        mpd = mpdClass.return_value = Mock(periods=[
+            Mock(adaptationSets=[
+                Mock(contentProtection=None,
+                     representations=[
+                         Mock(id=1, mimeType="video/mp4", height=720),
+                         Mock(id=2, mimeType="video/mp4", height=1080),
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='eng'),
+                         Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang='spa')
+                     ])
+            ])
+        ])
+
+        streams = DASHStream.parse_manifest(self.session, self.test_url)
+        mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
+
+        self.assertSequenceEqual(
+            sorted(list(streams.keys())),
+            sorted(["720p", "1080p"])
+        )
+
+        self.assertEqual(streams["720p"].audio_representation.lang, "eng")
+        self.assertEqual(streams["1080p"].audio_representation.lang, "eng")
+
+    @patch('streamlink.stream.dash.MPD')
+    def test_parse_manifest_audio_invalid_lang(self, mpdClass):
+        mpd = mpdClass.return_value = Mock(periods=[
+            Mock(adaptationSets=[
+                Mock(contentProtection=None,
+                     representations=[
+                         Mock(id=1, mimeType="video/mp4", height=720),
+                         Mock(id=2, mimeType="video/mp4", height=1080),
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='en_no_voice'),
+                     ])
+            ])
+        ])
+
+        streams = DASHStream.parse_manifest(self.session, self.test_url)
+        mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
+
+        self.assertSequenceEqual(
+            sorted(list(streams.keys())),
+            sorted(["720p", "1080p"])
+        )
+
+        self.assertEqual(streams["720p"].audio_representation.lang, "en_no_voice")
+        self.assertEqual(streams["1080p"].audio_representation.lang, "en_no_voice")
+
+    @patch('streamlink.stream.dash.MPD')
+    def test_parse_manifest_audio_multi_lang_locale(self, mpdClass):
+        self.session.localization.language.alpha2 = "es"
+        self.session.localization.explicit = True
+
+        mpd = mpdClass.return_value = Mock(periods=[
+            Mock(adaptationSets=[
+                Mock(contentProtection=None,
+                     representations=[
+                         Mock(id=1, mimeType="video/mp4", height=720),
+                         Mock(id=2, mimeType="video/mp4", height=1080),
+                         Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang='en'),
+                         Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang='es')
+                     ])
+            ])
+        ])
+
+        streams = DASHStream.parse_manifest(self.session, self.test_url)
+        mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
+
+        self.assertSequenceEqual(
+            sorted(list(streams.keys())),
+            sorted(["720p", "1080p"])
+        )
+
+        self.assertEqual(streams["720p"].audio_representation.lang, "es")
+        self.assertEqual(streams["1080p"].audio_representation.lang, "es")
+
     @patch('streamlink.stream.dash.MPD')
     def test_parse_manifest_drm(self, mpdClass):
         mpd = mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[Mock(contentProtection="DRM")])])
@@ -122,7 +221,7 @@ class TestDASHStream(unittest.TestCase):
     @patch('streamlink.stream.dash.DASHStreamReader')
     @patch('streamlink.stream.dash.FFMPEGMuxer')
     def test_stream_open_video_audio(self, muxer, reader):
-        stream = DASHStream(self.session, Mock(), Mock(id=1, mimeType="video/mp4"), Mock(id=2, mimeType="audio/mp3"))
+        stream = DASHStream(self.session, Mock(), Mock(id=1, mimeType="video/mp4"), Mock(id=2, mimeType="audio/mp3", lang='en'))
         open_reader = reader.return_value = Mock()
 
         stream.open()
@@ -202,7 +301,7 @@ class TestDASHStreamWorker(unittest.TestCase):
     @patch("streamlink.stream.dash_manifest.time.sleep")
     def test_duplicate_rep_id(self, sleep):
         representation_vid = Mock(id=1, mimeType="video/mp4", height=720)
-        representation_aud = Mock(id=1, mimeType="audio/aac")
+        representation_aud = Mock(id=1, mimeType="audio/aac", lang='en')
 
         mpd = Mock(dynamic=False,
                    publishTime=1,
diff --git a/tests/test_localization.py b/tests/test_localization.py
index 0b81ae59..90bb3ac3 100644
--- a/tests/test_localization.py
+++ b/tests/test_localization.py
@@ -32,11 +32,12 @@ class LocalizationTestsMixin(object):
         self.assertRaises(LookupError, l10n.Localization, "enUS")
 
     def test_equivalent(self):
-        l = l10n.Localization("en_US")
+        l = l10n.Localization("en_CA")
         self.assertTrue(l.equivalent(language="eng"))
         self.assertTrue(l.equivalent(language="en"))
-        self.assertTrue(l.equivalent(language="en", country="US"))
-        self.assertTrue(l.equivalent(language="en", country="United States"))
+        self.assertTrue(l.equivalent(language="en", country="CA"))
+        self.assertTrue(l.equivalent(language="en", country="CAN"))
+        self.assertTrue(l.equivalent(language="en", country="Canada"))
 
     def test_equivalent_remap(self):
         l = l10n.Localization("fr_FR")
@@ -48,7 +49,7 @@ class LocalizationTestsMixin(object):
         self.assertFalse(l.equivalent(language="eng"))
         self.assertFalse(l.equivalent(language="en"))
         self.assertFalse(l.equivalent(language="en", country="US"))
-        self.assertFalse(l.equivalent(language="en", country="United States"))
+        self.assertFalse(l.equivalent(language="en", country="Canada"))
         self.assertFalse(l.equivalent(language="en", country="ES"))
         self.assertFalse(l.equivalent(language="en", country="Spain"))
 
@@ -71,8 +72,8 @@ class LocalizationTestsMixin(object):
                          l10n.Localization.get_country("USA").alpha2)
         self.assertEqual("GB",
                          l10n.Localization.get_country("GB").alpha2)
-        self.assertEqual("United States",
-                         l10n.Localization.get_country("United States").name)
+        self.assertEqual("Canada",
+                         l10n.Localization.get_country("Canada").name)
 
     def test_get_country_miss(self):
         self.assertRaises(LookupError, l10n.Localization.get_country, "XE")