diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py
index 5c5b33010..a79d0629c 100644
--- a/youtube_dl/extractor/youtube.py
+++ b/youtube_dl/extractor/youtube.py
@@ -26,6 +26,7 @@ from ..compat import (
 )
 from ..jsinterp import JSInterpreter
 from ..utils import (
+    check_executable,
     clean_html,
     dict_get,
     error_to_compat_str,
@@ -1466,11 +1467,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
         super(YoutubeIE, self).__init__(*args, **kwargs)
         self._code_cache = {}
         self._player_cache = {}
-        self._webdriver = None
-
-    def __del__(self):
-        if self._webdriver is not None:
-            self._webdriver.quit()
+        self._webdriver_wrapper = None
 
     # *ytcfgs, webpage=None
     def _extract_player_url(self, *ytcfgs, **kw_webpage):
@@ -1680,40 +1677,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
         return ret
 
     def _call_n_function_with_webdriver(self, webdriver_type, jscode, n_param):
-        if self._webdriver is None:
-            wd = importlib.import_module('selenium.webdriver')
-            if webdriver_type == 'firefox':  # geckodriver
-                o = wd.FirefoxOptions()
-                o.headless = True
-                s = wd.firefox.service.Service(log_path=os.path.devnull)
-                self._webdriver = wd.Firefox(options=o, service=s)
-            elif webdriver_type == 'chrome':  # chromedriver
-                o = wd.ChromeOptions()
-                o.headless = True
-                """
-                If you are using the snap version of the chromium, chromedriver is included in the snap package.
-                You should use that driver.
-                $ cd /snap/bin && sudo ln -s -T chromium.chromedriver chromedriver
-                or
-                s = wd.chrome.service.Service(executable_path='chromium.chromedriver')
-                self._webdriver = wd.Chrome(options=o, service=s)
-                """
-                self._webdriver = wd.Chrome(options=o)
-            elif webdriver_type == 'edge':  # msedgedriver
-                o = wd.EdgeOptions()
-                o.headless = True
-                self._webdriver = wd.Edge(options=o)
-            elif webdriver_type == 'safari':  # safaridriver
-                """
-                safaridriver does not have headless-mode. :(
-                But macOS includes safaridriver by default.
-                To enable automation on safaridriver, run the following command once from the admin terminal.
-                # safaridriver --enable
-                """
-                self._webdriver = wd.Safari()
-            else:
-                raise ExtractorError('unsupported webdriver type: %s' % (webdriver_type))
-        self._webdriver.get('about:blank')
+        if self._webdriver_wrapper is None:
+            self._webdriver_wrapper = WebDriverJSWrapper(webdriver_type)
+        self._webdriver_wrapper.get('about:blank')
         funcname = self._extract_n_function_name(jscode)
         alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
         dummyfunc = ''.join(random.choice(alphabet) for _ in range(8))
@@ -1728,7 +1694,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
              'document.body.append(s);'
              'return {0}("{2}");'
              '}})("{3}");').format(dummyfunc, funcname, n_param, compat_urllib_quote(jscode))
-        n = self._webdriver.execute_script(f)
+        n = self._webdriver_wrapper.executeJS(f)
         return n
 
     def _extract_n_function_name(self, jscode):
@@ -3884,3 +3850,75 @@ class YoutubeTruncatedIDIE(InfoExtractor):
         raise ExtractorError(
             'Incomplete YouTube ID %s. URL %s looks truncated.' % (video_id, url),
             expected=True)
+
+
+class WebDriverJSWrapper(object):
+    """WebDriver Wrapper class"""
+
+    def __init__(self, webdriver_type, pageload_timeout=10, script_timeout=5):
+        self._webdriver = None
+        try:
+            wd = importlib.import_module('selenium.webdriver')
+        except ImportError as e:
+            self._raise_exception('Failed to import module "selenium.webdriver"', cause=e)
+
+        if webdriver_type == 'firefox':  # geckodriver
+            if not check_executable('geckodriver', ['--version']):
+                self._raise_exception('geckodriver not found in PATH')
+            o = wd.FirefoxOptions()
+            o.headless = True
+            s = wd.firefox.service.Service(log_path=os.path.devnull)
+            self._webdriver = wd.Firefox(options=o, service=s)
+        elif webdriver_type == 'chrome':  # chromedriver
+            if not check_executable('chromedriver', ['--version']):
+                self._raise_exception('chromedriver not found in PATH')
+            o = wd.ChromeOptions()
+            o.headless = True
+            """
+            If you are using the snap version of the chromium, chromedriver is included in the snap package.
+            You should use that driver.
+            $ cd /snap/bin && sudo ln -s -T chromium.chromedriver chromedriver
+            or
+            s = wd.chrome.service.Service(executable_path='chromium.chromedriver')
+            self._webdriver = wd.Chrome(options=o, service=s)
+            """
+            self._webdriver = wd.Chrome(options=o)
+        elif webdriver_type == 'edge':  # msedgedriver
+            if not check_executable('msedgedriver', ['--version']):
+                self._raise_exception('msedgedriver not found in PATH')
+            o = wd.EdgeOptions()
+            o.headless = True
+            self._webdriver = wd.Edge(options=o)
+        elif webdriver_type == 'safari':  # safaridriver
+            if not check_executable('safaridriver', ['--version']):
+                self._raise_exception('safaridriver not found in PATH')
+            """
+            safaridriver does not have headless-mode. :(
+            But macOS includes safaridriver by default.
+            To enable automation on safaridriver, run the following command once from the admin terminal.
+            # safaridriver --enable
+            """
+            self._webdriver = wd.Safari()
+        else:
+            self._raise_exception('unsupported type: %s' % (webdriver_type))
+        self._webdriver.set_page_load_timeout(pageload_timeout)
+        self._webdriver.set_script_timeout(script_timeout)
+
+    def __del__(self):
+        if self._webdriver is not None:
+            self._webdriver.quit()
+
+    def _raise_exception(self, msg, cause=None):
+        raise ExtractorError('[WebDriverJSWrapper] %s' % (msg), cause=cause)
+
+    def get(self, url):
+        """Loads a web page in the current browser session"""
+        self._webdriver.get(url)
+
+    def executeJS(self, jscode):
+        """Execute JS and return value"""
+        try:
+            ret = self._webdriver.execute_script(jscode)
+        except Exception as e:
+            self._raise_exception('Failed to execute JS', cause=e)
+        return ret