Repository: Flexget/Flexget

Issue:
Imdb_list: Login to IMDB failed. Check your credentials.
<!---
Before opening an issue, verify:

- Is this a feature request? Post it on https://feathub.com/Flexget/Flexget
- Is this an issue with webui? Make an issue over on https://github.com/Flexget/webui
- Did you recently upgrade? Look at the Change Log and Upgrade Actions to make sure that you don't need to make any changes to your config https://flexget.com/ChangeLog https://flexget.com/UpgradeActions
- Are you running FlexGet as a daemon? Stop it completely and then start it again https://flexget.com/CLI/daemon
- Did you search to see if the issue already exists? https://github.com/Flexget/Flexget/issues
- Did you fill out the issue template as completely as possible?

The issue template is here because it helps to ensure you submitted all the necessary information the first time, and allows us to more quickly review issues. Please fill it out correctly and do not ignore it, no matter how irrelevant you think it may be. Thanks in advance for your help with this!
--->

### Expected behaviour:
Imdb_list plugin to access watchlist queue on imdb site 
<!---
Please don't just say "it doesn't crash" or "it works". Explain what the expected result is.
--->

### Actual behaviour:
Imdb_list returns with message that login failed and to check my credentials. No changes to my imdb account has been made. It suddenly would no longer log in. 

### Steps to reproduce:
- Step 1: run any task with imdb_list plugin 

#### Config:
<details>
 <summary>(click to expand)</summary>

```
web_server: yes
variables: secret.yml
templates:
  global:
    no_entries_ok: yes
    notify:
      abort:
        via:
          - telegram:
              bot_token: '{? telegram.token ?}'
              parse_mode: markdown
              disable_previews: no
              recipients:
                - username: '{? telegram.usr ?}'


##################################################################
#    TV TEMPLATE
##################################################################

  vic_tv:
    set:
      path: /media/CHEWYHDD/CHEWY/Videos/temp
      move_completed_path: /media/CHEWYHDD/CHEWY/Videos/TV/NEW EPISODES/{{tvdb_series_name}}/Season {{tvdb_season}}/
      label: NEW EPISODES
    configure_series:
      from:
        trakt_list:
          username: '{? trak.usr ?}'
          account: '{? trak.acct ?}'
          list: vic tv
          type: shows
      settings:
        quality: 1080p
        propers: 16 hours
        specials: no
    verify_ssl_certificates: no
    thetvdb_lookup: yes
    series:
      - Shameless (2011):
          alternate_name: Shameless (US)
      - Tell Me a Story (2018):
          alternate_name: Tell Me a Story (US)
      - Real Time with Bill Maher (2003):
          identified_by: ep
      - Masterchef (2010):
          alternate_name: Masterchef (US)      
    deluge:
      host: localhost
      port: '{? deluge.port ?}'
      username: '{? deluge.usr ?}'
      password: '{? deluge.pwd ?}'

##################################################################
#    DOWNLOAD NOTIFICATION TEMPLATE
##################################################################


  telegram_notify:
    thetvdb_lookup: yes
    tvmaze_lookup: yes
    imdb_lookup: yes
    tmdb_lookup: yes
    notify:
      entries:
        title: 'flexget {{task}}'
        message: |+
          {% if series_name is defined -%}
          *{{series_name}}* - {{series_id}} - {{quality|d('')}}
          *{{tvmaze_ep_name|d(tvdb_ep_name)|d('')}}*
          *Air date:* {{tvdb_ep_air_date|d(tvmaze_episode_airdate)|d('')}}
          *Summary:* {{tvdb_ep_overview}}
          [Image]({{tvmaze_series_original_image|replace("_", "%5F")}})
          [Show page]({{tvmaze_series_url|replace("_", "%5F")}})
          {% elif imdb_name is defined -%}
          *{{imdb_name}}* - ({{imdb_year}})
          {{quality|d('')}}
          {{imdb_score}}/10 - {{imdb_votes}} votes
          {{imdb_genres|join(', ')|title}} 
          *Plot:* {{imdb_plot_outline}}
          [Image]({{tmdb_posters[0]|replace("_", "%5F")}})
          [Movie Page]({{imdb_url|d('')}})
          {% else -%}
          {{title}}
          {%- endif -%}
        via:
          - telegram:
              bot_token: '{? telegram.token ?}'
              parse_mode: markdown
              disable_previews: no
              recipients:
                - username: '{? telegram.usr ?}'


##################################################################
#   MOVIE TEMPLATE
##################################################################

  movie:
    tmdb_lookup: yes 
    imdb_lookup: yes
    proper_movies: no
    content_size:
      max: 5000
      strict: no
    content_filter: 
      reject:
        - '*.zip'
        - '*.wmv'
        - '*.wma'
        - '*[cC]odec*'
        - '*[rR]eadme*'
    exists_movie:
      - /media/CHEWYHDD/CHEWY/Videos/Movies
      - /media/CHEWYHDD/CHEWY/Videos/Addison/Addison Movies


#################################################################
#    FILTERS TEMPLATES
##################################################################

  filters:
    regexp:
      reject:
        - \bmsd\b: {from: title}
        - \bgreek\b: {from: title}
        - \bgerman\b: {from: title}
        - \bfrench\b: {from: title}
        - \brussian\b: {from: title}
        - \bswedish\b: {from: title}
        - \bspanish\b: {from: title}
        - \bhindi\b: {from: title}
        - \barabic\b: {from: title}
        - \bitalian\b: {from: title}
        - \bpolish\b: {from: title}
        - \bromanian\b: {from: title}
        - \bdutch\b: {from: title}
        - \bczech\b: {from: title}
        - \bturkish\b: {from: title}
        - \brmvb\b: {from: title}
#        - \bkorean\b: {from: title}
        - \bwmv\b: {from: title}
#        - (s|d)ub(s|bed)?\b: {from: title}
        - \bFRENCH\b: {from: title}
        - \bSPANiSH\b: {from: title}
        - \bLatino\b: {from: title}
        - \btrailer\b: {from: title}
        - \bHDTC\b: {from: title} 
        - \bHDTS\b: {from: title}
        - \bHQTS\b: {from: title}
        - \bHDcam\b: {from: title} 
        - \bR5\b: {from: title}
        - \b3-?D\b: {from: title}                             # I don't have any 3D displays
        - \btrailer\b: {from: title}                          # I've gotten a few trailers that matched as movies. VERY annoying
        - \bTS\b: {from: title}
        - \bCam\b: {from: title}
        - '{C_P}': {from: title}                              # The following are groups with poor quality releases
        - TrTd TeaM: {from: title}
        - \[TNTVillage\]: {from: title}
        - \bFLEET\b: {from: title}
        - \b0SEC\b: {from: title}
        - \[facepalm\]: {from: title}
        - FASTSUB: {from: title}
        - VOSTFR: {from: title}
        - Subtitulado: {from: title}
        - \bNORDiC\b: {from: title}
        - \biPad\b: {from: title}
#        - \b(ita|ger|fra|spa|swe|nor|nordic|fr|kor|uk|esp|nl|pl|spanish)\b: {from: title}
        - \bR6\b: {from: title}
        - \bTemporada\b: {from: title}
        - \bDual\b: {from: title}
        - \bTamil*\b: {from: title}
        - \bJapanese\b: {from: title}
        - \bJajji!\b: {from: title}
        - \bdragons.den.(ca|uk)\b: {from: title}
        - \bx265\b: {from: title}
#        - \HC\b: {from: title}
        - \b480p\b: {from: title}
        - \b.TamilRock*\b: {from: title}
        - \b1xbet\b: {from: title}
        - \bCAMRip\b: {from: title}
        - \bHDCAMRip\b: {from: title}


##################################################################
#    TASK SCHEDULES
##################################################################


schedules:

  - tasks: tv_shows
    interval:
      minutes: 5

  - tasks: IMDB
    interval:
      minutes: 30


  - tasks: passthepopcorn
    interval: 
      hours: 2

  - tasks: movies
    interval:
      hours: 1


##################################################################
#    TASKS 
##################################################################


tasks:

  tv_shows:
    cfscraper: yes
    seen_info_hash: local
    priority: 1
    template:
      - vic_tv
      - telegram_notify
      - filters
    inputs:
      - rss: '{? btn.url ?}'
#      - rss: '{? mtv.all ?}'


  IMDB:
    cfscraper: yes
    seen_info_hash: local
    imdb_list:
      login: '{? imdb.usr ?}'
      password: '{? imdb.pwd ?}'
      list: watchlist
    accept_all: yes
    imdb_lookup: yes
    tmdb_lookup: yes
    list_add:
      - movie_list: vic_movies
    priority: 2


  list_cleanup:
    movie_list: vic_movies
    crossmatch:
      from:
        - imdb_list:
            login: '{? imdb.usr ?}'
            password: '{? imdb.pwd ?}'
            list: watchlist
      action: reject
      fields: [imdb_id]
    accept_all: yes
    list_remove:
      - movie_list: vic_movies
    seen: no



  passthepopcorn:
    priority: 4
    template:
      - movie
      - telegram_notify
      - filters
    quality: hdrip+
    imdb_lookup: yes
    list_match:
      from:
        - movie_list: vic_movies
    list_add:
      - entry_list: downloaded_movies
    list_remove:
      - imdb_list:
          login: '{? imdb.usr ?}'
          password: '{? imdb.pwd ?}'
          list: watchlist
    verify_ssl_certificates: no
    inputs:
      - rss: '{? ptp.url ?}'
    set:
      path: /media/CHEWYHDD/CHEWY/Videos/temp
      move_completed_path: /media/CHEWYHDD/CHEWY/Videos/Movies/
    deluge:
      host: localhost
      port: '{? deluge.port ?}'
      username: '{? deluge.usr ?}'
      password: '{? deluge.pwd ?}'
      label: Movies

  movies:
    priority: 5
    cfscraper: yes
    seen_info_hash: local
    template:
      - movie
      - telegram_notify
      - filters
    discover:
      release_estimations: 
        optimistic: 60 days
      what:
        - movie_list: vic_movies
      from:
        - yts: yes
        - rarbg:
            category: [14, 15, 16, 17, 21, 22, 42, 44, 45, 46, 47, 48]
        - 1337x: yes
        - piratebay:
            category: movies
    interval: 1 hour
    quality: 720p+
    list_match:
      from:
        - movie_list: vic_movies
    list_add:
      - entry_list: downloaded_movies
    list_remove:
      - imdb_list:
          login: '{? imdb.usr ?}'
          password: '{? imdb.pwd ?}'
          list: watchlist
    torrent_alive: 10
    verify_ssl_certificates: no
    set:
      path: /media/CHEWYHDD/CHEWY/Videos/temp
      move_completed_path: /media/CHEWYHDD/CHEWY/Videos/Movies/
    deluge:
      host: localhost
      port: '{? deluge.port ?}'
      username: '{? deluge.usr ?}'
      password: '{? deluge.pwd ?}'
      ratio: .01
      label: Public      
      


```
</details>
  
#### Log:
<details>
 <summary>(click to expand)</summary>

```
(flexget) pi@pi4:~ $ flexget --debug execute --tasks IMDB2020-04-30 16:15:53 DEBUG    manager                       Figuring out config load paths
2020-04-30 16:15:53 DEBUG    manager                       Adding virtualenv path
2020-04-30 16:15:53 DEBUG    manager                       Found config: /home/pi/flexget/config.yml
2020-04-30 16:15:53 DEBUG    manager                       Config file /home/pi/flexget/config.yml selected
2020-04-30 16:15:53 DEBUG    manager                       sys.defaultencoding: utf-8
2020-04-30 16:15:53 DEBUG    manager                       sys.getfilesystemencoding: utf-8
2020-04-30 16:15:53 DEBUG    manager                       flexget detected io encoding: utf-8
2020-04-30 16:15:53 DEBUG    manager                       os.path.supports_unicode_filenames: False
There is a FlexGet process already running for this config, sending execution there.
2020-04-30 16:15:53 DEBUG    manager                       Sending command to running FlexGet process: ['--debug', 'execute', '--tasks', 'IMDB']
2020-04-30 16:15:53 DEBUG    cron_env                      Encoding utf-8 stored
2020-04-30 16:15:53 DEBUG    util.simple_persistence                 setting key terminal_encoding value 'utf-8'
2020-04-30 16:15:53 DEBUG    task          IMDB            executing IMDB
2020-04-30 16:15:53 DEBUG    template      IMDB            Merging template global into task IMDB
2020-04-30 16:15:54 DEBUG    imdb_list     IMDB            fetching items from IMDB
2020-04-30 16:15:54 DEBUG    imdb_list     IMDB            login credentials found in cache, testing
2020-04-30 16:15:54 DEBUG    utils.requests IMDB            GETing URL https://www.imdb.com/profile with args () and kwargs {'allow_redirects': True, 'timeout': 30}
2020-04-30 16:15:54 DEBUG    imdb_list     IMDB            cache credentials expired
2020-04-30 16:15:54 DEBUG    imdb_list     IMDB            user credentials not found in cache or outdated, fetching from IMDB
2020-04-30 16:15:54 VERBOSE  utils.requests IMDB            Waiting 4.49 seconds until next request to imdb.com
2020-04-30 16:15:59 DEBUG    utils.requests IMDB            GETing URL https://www.imdb.com with args () and kwargs {'allow_redirects': True, 'timeout': 30}
2020-04-30 16:15:59 VERBOSE  utils.requests IMDB            Waiting 4.26 seconds until next request to imdb.com
2020-04-30 16:16:04 DEBUG    utils.requests IMDB            GETing URL https://www.imdb.com/ap/signin?openid.return_to=https%3A%2F%2Fwww.imdb.com%2Fap-signin-handler&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.assoc_handle=imdb_mobile_us&openid.mode=checkid_setup&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0 with args () and kwargs {'allow_redirects': True, 'timeout': 30}
2020-04-30 16:16:05 DEBUG    imdb_list     IMDB            email=********, password=********
2020-04-30 16:16:05 DEBUG    utils.requests IMDB            Waiting 3.35 seconds until next request to imdb.com
2020-04-30 16:16:09 DEBUG    utils.requests IMDB            POSTing URL https://www.imdb.com/ap/signin with args () and kwargs {'data': {'appActionToken': 'j2FcSMAoZBAyj2BPbBj2F3rSvcYXuxZJsj3D', 'appAction': 'SIGNIN', 'openid.return_to': 'ape:aHR0cHM6Ly93d3cuaW1kYi5jb20vYXAtc2lnbmluLWhhbmRsZXI=', 'prevRID': 'ape:MFA2VFZDMzQ4MkNIODVLQVdWQlE=', 'workflowState': 'eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiQTI1NktXIn0.N5plGBribvbepPlzd0b1Io5Aw7qVnL20MzbekLv7zOJKEUGdKLDSDw.CXL6nepEGKtTtALU.d6uTuoFhaFVmr7TJmVH76wk-vX0C51yZtNp3g7XZn4qJiYyckMFSng89p41kiLLgWsMT7Mlybz3ym3N_FqULFIgWUHepvKbzDpX6-T5pvvGs7N_QdMl5bckd1dB0VhYO0iNPT3a_0KYJlJ4qPUftJiTYUSSf_opTgjRA8QKKwgA_MYaEf_7sxuwGEcAWJikueI_80n7WDDym_pw_fmyZTO3YfljewcUDyvU7FxmeAt7K1PBDOHDLo02r3wkJjY-pSHxESm5yi8_Xm6jqKGLhzcEBfO-4UrCNoMXNBg.LGARjhbrlpxIYfmF8ARXEQ', 'email': '********', 'password': '********', 'showPasswordChecked': 'true'}, 'json': None, 'timeout': 30}
2020-04-30 16:16:09 VERBOSE  utils.requests IMDB            Waiting 4.65 seconds until next request to imdb.com
2020-04-30 16:16:14 DEBUG    utils.requests IMDB            GETing URL https://www.imdb.com/profile with args () and kwargs {'allow_redirects': True, 'timeout': 30}
2020-04-30 16:16:14 CRITICAL plugin        IMDB            Login to IMDB failed. Check your credentials.
2020-04-30 16:16:14 WARNING  task          IMDB            Aborting task (plugin: imdb_list)
2020-04-30 16:16:16 DEBUG    notify_entry  IMDB            sending abort notification
2020-04-30 16:16:16 DEBUG    notify        IMDB            Sending a notification to `telegram`
2020-04-30 16:16:16 DEBUG    telegram      IMDB            token=****, parse_mode=markdown, disable_previews=False, usernames=['ch***'], fullnames=[], groups=[]
2020-04-30 16:16:16 DEBUG    telegram      IMDB            loading cached chat ids
2020-04-30 16:16:17 DEBUG    telegram      IMDB            found 1 cached chat_ids: ['id=**** username=ch**** firstname=']
2020-04-30 16:16:17 DEBUG    telegram      IMDB            all chat ids found in cache
2020-04-30 16:16:17 DEBUG    telegram      IMDB            chat_ids=[<flexget.components.notify.notifiers.telegram.ChatIdEntry object at 0xa4c18d50>]
2020-04-30 16:16:17 DEBUG    telegram      IMDB            sending msg to telegram servers: Reason: Login to IMDB failed. Check your credentials.
2020-04-30 16:16:17 VERBOSE  notify        IMDB            Successfully sent a notification to `telegram`
(flexget) pi@pi4:~ $
```
</details>

### Additional information:

- FlexGet version: v3.1.51
- Python version: 3.7
- Installation method: Raspberry Pi 4 virtualenv
- Using daemon (yes/no): yes
- OS and version: raspbian buster
- Link to crash log:

<!---
In config and debug/crash logs, remember to redact any personal or sensitive information such as passwords, API keys, private URLs and so on.

Please verify that the following data is present before submitting your issue:

- Link to a paste service or paste above the relevant config (preferably full config, including templates if present). Please make sure the paste does not expire, if possible.
- Link to a paste service or paste above debug-level logs of the relevant task/s (use `flexget -L debug execute --tasks <Task_name>`).
- FlexGet version (use `flexget -V` to get it).
- Full Python version, for example `2.7.11` (use `python -V` to get it). 
- Installation method (pip, git install, etc).
- Whether or not you're running FlexGet as a daemon.
- OS and version.
- Attach crash log if one was generated, in addition to the debug-level log. It can be found in the directory with your config file.
--->



Discussion:
Same issue here running Flexget: 3.1.51 on docker.
Any updates on this one? 
This issue is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 30 days.
I'm still hoping for an update on this 
Seems like this is still an issue? In the meantime I've switched to Trakt watchlist but their site is so terribly slow.
@grantrules yes, I still can't log in. I've been using imdb_watchlist but that doesn't remove accepted movies from my imdb queue on the website. So using watchlist is a bandaid solution for me 
Switched to trakt movie list a long time ago, can manage movies and TV in one place too.
> Switched to trakt movie list a long time ago, can manage movies and TV in one place too.

I probably would have switched too, if trakt.tv had a good mobile app. 

> I probably would have switched too, if trakt.tv had a good mobile app.

It does on iOS: https://twitter.com/watchtapp
> > I probably would have switched too, if trakt.tv had a good mobile app.
> 
> It does on iOS: https://twitter.com/watchtapp

Android user here 😬
> I probably would have switched too, if trakt.tv had a good mobile app.

TBF, they do have a responsive site. I use that with a "desktop icon" on mobile, don't miss a separate app. But since that's off-topic I'm fine with leaving at that 😛
> > I probably would have switched too, if trakt.tv had a good mobile app.
> 
> TBF, they do have a responsive site. I use that with a "desktop icon" on mobile, don't miss a separate app. But since that's off-topic I'm fine with leaving at that 😛

Does trakt.tv list plugin even have the option to remove from queue after match, from the the website? 
> Does trakt.tv list plugin even have the option to remove from queue after match, from the the website?

You just add a `list_remove` plugin instance for it in the task.
> Does trakt.tv list plugin even have the option to remove from queue after match, from the the website?

I have a working example (TV/TV4K/Movies with automatic cleanup) on my github if you're interested :)

Resolving patch:
diff --git a/flexget/components/managed_lists/lists/imdb_list.py b/flexget/components/managed_lists/lists/imdb_list.py
--- a/flexget/components/managed_lists/lists/imdb_list.py
+++ b/flexget/components/managed_lists/lists/imdb_list.py
@@ -2,6 +2,8 @@
 import re
 from collections.abc import MutableSet
 from datetime import datetime
+from json import JSONDecodeError, loads as json_loads, load as json_load
+from pathlib import Path
 
 from loguru import logger
 from requests.exceptions import RequestException
@@ -64,12 +66,25 @@ class ImdbEntrySet(MutableSet):
         'type': 'object',
         'properties': {
             'login': {'type': 'string'},
-            'password': {'type': 'string'},
+            'cookies': {
+                'oneOf': [
+                    {'type': 'string', 'format': 'file'},
+                    {'type': 'string', 'format': 'json'},
+                    {
+                        'type': 'object',
+                        'properties': {
+                            'ubid-main': {'type': 'string'},
+                            'sess-at-main': {'type': 'string'},
+                        },
+                    },
+                ],
+                'error_oneOf': 'Please inform a dict with the cookies, a string in json format, or a path to the file',
+            },
             'list': {'type': 'string'},
             'force_language': {'type': 'string', 'default': 'en-us'},
         },
         'additionalProperties': False,
-        'required': ['login', 'password', 'list'],
+        'required': ['login', 'cookies', 'list'],
     }
 
     def __init__(self, config):
@@ -79,11 +94,49 @@ def __init__(self, config):
         self._session.headers.update({'Accept-Language': config.get('force_language', 'en-us')})
         self.user_id = None
         self.list_id = None
-        self.cookies = None
+        self.cookies = self.parse_cookies(config.get('cookies', None))
         self.hidden_value = None
         self._items = None
         self._authenticated = False
 
+    def parse_cookies(self, cookies):
+        required_fields = ['ubid-main', 'at-main']
+
+        if not cookies:
+            raise PluginError('Please inform the login cookies')
+
+        if isinstance(cookies, dict):
+            new_cookie = cookies
+        elif isinstance(cookies, str):
+            try:
+                new_cookie = json_loads(cookies)
+            except JSONDecodeError as e:
+                new_cookie = self.parse_cookies_file(cookies)
+
+        if not new_cookie:
+            raise PluginError(
+                'Invalid cookies format, please add a dict, a string in json or a path to a file in json'
+            )
+
+        for field in required_fields:
+            if field not in new_cookie:
+                raise PluginError(f'Invalid cookies format, missing \'{field}\'')
+
+        return new_cookie
+
+    def parse_cookies_file(self, path):
+        file = Path(path)
+        if not file.exists():
+            raise PluginError('Invalid cookies file format, file does not exist')
+
+        with file.open(encoding='utf-8') as data:
+            try:
+                contents = json_load(data)
+            except JSONDecodeError as e:
+                raise PluginError('Invalid cookies file format, file not in json')
+
+        return contents
+
     @property
     def session(self):
         if not self._authenticated:
@@ -117,21 +170,33 @@ def authenticate(self):
         """Authenticates a session with IMDB, and grabs any IDs needed for getting/modifying list."""
         cached_credentials = False
         with Session() as session:
-            user = (
-                session.query(IMDBListUser)
-                .filter(IMDBListUser.user_name == self.config.get('login'))
-                .one_or_none()
-            )
-            if user and user.cookies and user.user_id:
-                logger.debug('login credentials found in cache, testing')
-                self.user_id = user.user_id
-                if not self.get_user_id_and_hidden_value(cookies=user.cookies):
-                    logger.debug('cache credentials expired')
-                    user.cookies = None
-                    self._session.cookies.clear()
-                else:
-                    self.cookies = user.cookies
-                    cached_credentials = True
+            if self.cookies:
+                if not self.user_id:
+                    self.user_id = self.get_user_id_and_hidden_value(self.cookies)
+                if not self.user_id:
+                    raise PluginError(
+                        'Not possible to retrive userid, please check cookie information'
+                    )
+
+                user = IMDBListUser(self.config['login'], self.user_id, self.cookies)
+                self.cookies = user.cookies
+                cached_credentials = True
+            else:
+                user = (
+                    session.query(IMDBListUser)
+                    .filter(IMDBListUser.user_name == self.config.get('login'))
+                    .one_or_none()
+                )
+                if user and user.cookies and user.user_id:
+                    logger.debug('login credentials found in cache, testing')
+                    self.user_id = user.user_id
+                    if not self.get_user_id_and_hidden_value(cookies=user.cookies):
+                        logger.debug('cache credentials expired')
+                        user.cookies = None
+                        self._session.cookies.clear()
+                    else:
+                        self.cookies = user.cookies
+                        cached_credentials = True
             if not cached_credentials:
                 logger.debug('user credentials not found in cache or outdated, fetching from IMDB')
                 url_credentials = (
diff --git a/flexget/config_schema.py b/flexget/config_schema.py
--- a/flexget/config_schema.py
+++ b/flexget/config_schema.py
@@ -4,6 +4,7 @@
 from collections import defaultdict
 from typing import Any, Callable, Dict, List, Match, Optional, Pattern, Union
 from urllib.parse import parse_qsl, urlparse
+from json import JSONDecodeError, loads as json_loads
 
 import jsonschema
 from jsonschema import ValidationError
@@ -308,6 +309,19 @@ def is_valid_template(instance) -> bool:
     return get_template(instance) is not None
 
 
+@format_checker.checks('json', raises=ValueError)
+def is_json(instance) -> bool:
+    if not isinstance(instance, str):
+        return False
+
+    try:
+        decoded_json = json_loads(instance)
+    except JSONDecodeError as e:
+        raise ValueError('`%s` is not a valid json' % instance)
+
+    return True
+
+
 def set_error_message(error: jsonschema.ValidationError) -> None:
     """
     Create user facing error message from a :class:`jsonschema.ValidationError` `error`


Test patch: