Code Monkey home page Code Monkey logo

pymsl's Introduction

pymsl

Build Status License: GPL v3

Python library for interacting with the Netflix MSL API

Usage

Basic Usage

>>> import pymsl
>>> user_auth_data = {
...     'scheme': 'EMAIL_PASSWORD',
...     'authdata': {
...         'email': email,
...         'password': password
...     }
... }
>>> client = pymsl.MslClient(user_auth_data)
>>> client.load_manifest(80092521)
{'version': 2, ...

All user authentication schemes are defined in the MSL wiki: https://github.com/Netflix/msl/wiki/User-Authentication-(Configuration)

Custom Kwargs

pymsl.MslClient() takes additional kwargs as well to override the defaults; the only required arg for initialization is user_auth_data:

>>> pymsl.MslClient(
...     user_auth_data,
...     esn=CUSTOM_ESN, # default is NFCDCH-02-[random device ID]
...     drm_system=CUSTOM_DRM_SYSTEM, # default is 'widevine', you can use 'playready', 'fps', etc.
...     profiles=LIST_OF_PROFILES, # default is ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'heaac-2-dash', 'simplesdh', 'nflx-cmisc', 'BIF240', 'BIF320']
...     keypair=CUSTOM_CRYPTODOME_RSA_KEYPAIR, # default is a random 2048-bit keypair
...     message_id=CUSTOM_MESSAGE_ID, # default is a random integer between 0 and 2^52
...     languages=LIST_OF_LANGUAGES, # default is ['en_US']
...     proxies=PROXIES, # default is None
...     key_request_data=CUSTOM_KEY_REQUEST_DATA, # default is ASYMMETRIC_WRAPPED
...     extra_manifest_params=EXTRA_MANIFEST_PARAMS # default is a blank dict
... )
  • esn is the identity used for communicating with MSL. Different ESNs have different privileges.
  • drm_system will determine what kind of initialization data you will receive in the manifest.
  • profiles is a list of profiles used for telling MSL what you want to receive in the manifest.
  • keypair is the RSA keypair used in the initial key exchange.
  • message_id is a random integer used for identifying the MSL client session.
  • languages is a list of languages used for determining the language of the manifest received.
  • proxies is a proxy dict passed the same way you would pass it to the requests library.
  • key_request_data is a dict passed to override the normal ASYMMETRIC_WRAPPED key request dict in order to enable using other key exchange mechanisms. Note that you may have to monkey patch the parse_handshake function in order for it to work with your specified key exchange mechanism.
  • extra_manifest_params is a dict of extra manifest params. Here's the default manifest params sent in a manifest request:
'params': {
    'type': 'standard',
    'viewableId': viewable_id,
    'profiles': self.msl_session['profiles'],
    'flavor': 'STANDARD',
    'drmType': self.msl_session['drm_system'],
    'drmVersion': 25,
    'usePsshBox': True,
    'isBranching': False,
    'useHttpsStreams': True,
    'imageSubtitleHeight': 720,
    'uiVersion': 'shakti-v4bf615c3',
    'clientVersion': '6.0011.511.011',
    'supportsPreReleasePin': True,
    'supportsWatermark': True,
    'showAllSubDubTracks': False,
    'videoOutputInfo': [
        {
            'type': 'DigitalVideoOutputDescriptor',
            'outputType': 'unknown',
            'supportedHdcpVersions': [],
            'isHdcpEngaged': False
        }
    ],
    'preferAssistiveAudio': False,
    'isNonMember': False
}

By using this kwarg you can add any values you want to this param dict. For example, if you wanted showAllSubDubTracks to be true, you would set extra_manifest_params to {'showAllSubDubTracks': True}. The manifest param dict is simply .update()'ed with extra_manifest_params, so you can overwrite default values or add new ones.

Methods

load_manifest(viewable_id)

@param viewable_ids: Int of viewable ID
                     to obtain manifest for

@return: manifest (dict)

This function performs a manifest request based on
the parameters supplied when initalizing the client
object. If there are no errors, it will return the
manifest as a dict. If there are errors, it will
raise a ManifestError exception with the response
from the MSL API as the body.

get_license(challenge, session_id)

@param challenge:  EME license request as a byte string
                   that will be used to obtain a license

@param session_id: DRM specific session ID passed as a string

@return: license (dict)

This function performs a license request based on
the parameters supplied when initalizing the client
object. If there are no errors, it will return the
licenses as a list of dicts. If there are errors, it will
raise a LicenseError exception with the response
from the MSL API as the body.

Installation

To install, you can either clone the repository and run python setup.py install or you can run pip install pymsl

To-Do

  • Implement license acquisition
  • Clean up chunked payload parsing

pymsl's People

Contributors

qnorsten avatar truedread avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pymsl's Issues

Error parsing MSL encodable

Using the basic usage example:

auth_data = {
    'scheme': 'EMAIL_PASSWORD',
    'auth_data': {
        'email': '[email protected]',
        'password': 'password'
    }
}

client = pymsl.MslClient(auth_data)
client.load_manifest(80092521)

raises pymsl.exceptions.ManifestError: Error parsing MSL encodable.

Error in getting licence

Another error

'dataBase64': base64.b64encode(challenge).decode('utf-8'),

File "/usr/lib/python2.7/base64.py", line 54, in b64encode
encoded = binascii.b2a_base64(s)[:-1]
TypeError: b2a_base64() argument 1 must be string or buffer, not int

Any idea?

Errror in manifest request with NFCDCH-02- ESN

profiles = ['playready-h264hpl30-dash', 'playready-h264hpl31-dash', 'playready-h264hpl40-dash', 'playready-h264mpl30-dash' 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'dfxp-ls-sdh']

client = pymsl.MslClient(
			{'scheme': 'EMAIL_PASSWORD', 
						'authdata': {
									'email': username,
									'password': password
									}
			},
			esn = utils_generate_esn('NFCDCH-02-'),
			drm_system = 'widevine',
			profiles = profiles,
			extra_manifest_params = {
									'showAllSubDubTracks': showAllSubDubTracks
									}
		)

manifest = client.load_manifest(nfID)['result']
print(manifest)

pywidevine.pymsl.exceptions.ManifestError: Entity used incorrect user authentication data type.

Issue to get manifest for some shows

Hello

I tried to get the manifest with this code

The show is "Girl from Nowhere" (https://www.netflix.com/be-fr/title/80241947)

import pymsl

user_auth_data = {
      'scheme': 'EMAIL_PASSWORD',
      'authdata': {
          'email': 'xxx',
          'password': 'xxx'
      }
  }

client = pymsl.MslClient(user_auth_data)

client.load_manifest(80241947)

But I got this error

pymsl.exceptions.ManifestError: {'version': 2, 'id': 15429961728572, 'serverTime': 1636250607561, 'from': '[email protected]/[email protected]', 'error': {'pboc': True, 'code': 'FAIL', 'detail': 'manifest/pbcs-512: Viewable is not a movie or episode. (E3-BQFRAAELEKp7d3Kw3Kid0WYMwQELqo-Aw9hoWr4IzNi0fKjD7DZ7xwap-VG_1OqLossBNsTTPan3wLWeYYKhEHnZUegK1NExv7IGJN4Bpv-Sczk-LnP_eZQo4toiZiBGK5VO8BkKEDSbyZAciT5MWE8VTZRTXHpOwuSKglrc4OIk1FKrmH1SLI3C65Te1lOy5yFh_RYOR_zwiAv-8IYEjAXlqpqILThMZQ1NgHtOKpP-8ToUVlmIW1gX2_NGF-A8TnCm6g2jBevyrI_JHXwi5EiE2IU-ulbddd--dQ==) [viewableId=80241947] ([email protected]/[email protected])', 'display': 'This title is not available to watch instantly. Please try another title.', 'alertTag': '', 'errorDisplayMessage': 'This title is not available to watch instantly. Please try another title.', 'errorActionId': 3, 'nccpError': {}, 'errorSubCode': 0, 'errorReasonCode': 0, 'errorNccpCode': 0, 'errorExternalCode': 0, 'bladeRunnerMessage': 'manifest/pbcs-512: Viewable is not a movie or episode. (E3-BQFRAAELEKp7d3Kw3Kid0WYMwQELqo-Aw9hoWr4IzNi0fKjD7DZ7xwap-VG_1OqLossBNsTTPan3wLWeYYKhEHnZUegK1NExv7IGJN4Bpv-Sczk-LnP_eZQo4toiZiBGK5VO8BkKEDSbyZAciT5MWE8VTZRTXHpOwuSKglrc4OIk1FKrmH1SLI3C65Te1lOy5yFh_RYOR_zwiAv-8IYEjAXlqpqILThMZQ1NgHtOKpP-8ToUVlmIW1gX2_NGF-A8TnCm6g2jBevyrI_JHXwi5EiE2IU-ulbddd--dQ==) [viewableId=80241947] ([email protected]/[email protected])', 'bladeRunnerCode': '512'}}

If I use the viewable ID of the first episode, it's working. Any ideas, what does it make go wrong?

Thanks for your help.

Weird behavior related to profiles

Hello, it looks that profiles have a weird behavior.

I'm still doing my test on episode 1 of Girl From Nowhere

The default in the README are not the same that in https://github.com/truedread/pymsl/blob/master/pymsl/client.py#L26

...     profiles=LIST_OF_PROFILES, # default is ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'heaac-2-dash', 'simplesdh', 'nflx-cmisc', 'BIF240', 'BIF320']

But what is weird are the result when I add the VP9 profiles it looks like the others are removed, is that expected?

Without VP9 profiles

client = pymsl.MslClient(user_auth_data, profiles=[
  'playready-h264mpl30-dash',
  'playready-h264mpl31-dash',
  'playready-h264mpl40-dash',
  'heaac-2-dash',
  'simplesdh',
  'nflx-cmisc',
  'BIF240',
  'BIF320'])

a = client.load_manifest(80241859)

for i, j in enumerate(a['result']['video_tracks'][0]['streams']):
  print('VIDEO: {} - PROFILE {} - BITRATE {} - RESOLUTION {}:{}'.format(
        i, j['content_profile'], j['bitrate'], str(j['crop_w']), str(j['crop_h']))
  )
VIDEO: 0 - PROFILE playready-h264mpl30-dash - BITRATE 140 - RESOLUTION 320:240
VIDEO: 1 - PROFILE playready-h264mpl30-dash - BITRATE 180 - RESOLUTION 384:288
VIDEO: 2 - PROFILE playready-h264mpl30-dash - BITRATE 270 - RESOLUTION 512:384
VIDEO: 3 - PROFILE playready-h264mpl30-dash - BITRATE 380 - RESOLUTION 512:384
VIDEO: 4 - PROFILE playready-h264mpl30-dash - BITRATE 560 - RESOLUTION 720:480
VIDEO: 5 - PROFILE playready-h264mpl30-dash - BITRATE 830 - RESOLUTION 720:480
VIDEO: 6 - PROFILE playready-h264mpl31-dash - BITRATE 1210 - RESOLUTION 1280:720
VIDEO: 7 - PROFILE playready-h264mpl40-dash - BITRATE 1540 - RESOLUTION 1920:1080
VIDEO: 8 - PROFILE playready-h264mpl40-dash - BITRATE 2260 - RESOLUTION 1920:1080
VIDEO: 9 - PROFILE playready-h264mpl40-dash - BITRATE 3320 - RESOLUTION 1920:1080

With VP9 profiles

client = pymsl.MslClient(user_auth_data, profiles=[
  'playready-h264mpl30-dash',
  'playready-h264mpl31-dash',
  'playready-h264mpl40-dash',
  'vp9-profile0-L30-dash-cenc',
  'vp9-profile0-L31-dash-cenc',
  'vp9-profile0-L40-dash-cenc',
  'heaac-2-dash',
  'simplesdh',
  'nflx-cmisc',
  'BIF240',
  'BIF320'])

a = client.load_manifest(80241859)

for i, j in enumerate(a['result']['video_tracks'][0]['streams']):
  print('VIDEO: {} - PROFILE {} - BITRATE {} - RESOLUTION {}:{}'.format(
        i, j['content_profile'], j['bitrate'], str(j['crop_w']), str(j['crop_h']))
  )
VIDEO: 0 - PROFILE vp9-profile0-L30-dash-cenc - BITRATE 104 - RESOLUTION 768:432
VIDEO: 1 - PROFILE vp9-profile0-L30-dash-cenc - BITRATE 164 - RESOLUTION 960:540
VIDEO: 2 - PROFILE vp9-profile0-L30-dash-cenc - BITRATE 263 - RESOLUTION 960:540
VIDEO: 3 - PROFILE vp9-profile0-L31-dash-cenc - BITRATE 425 - RESOLUTION 1280:720
VIDEO: 4 - PROFILE vp9-profile0-L40-dash-cenc - BITRATE 800 - RESOLUTION 1920:1080

Thanks for your help.

Bad gateway when trying to load_manifest

Hi everyone,

Few days ago, I got now an index list error when i'm trying to retrieve the manifest.

By printing the http reponse I see that it got a 502 gatway error.

I also tried another login scheme like NETLIXID instead of the casual EMAIL_PASSWORD but it gives the same issue. I'm guessing that the way of asking the manifest changed but I'm not good enough for trying to decode what is happening in MSL in the browser directly.

If someone has tips or maybe the solution, thank you.

Error in getting manifest

I tried the sample code with the correct email and password and am getting an error ManifestError: Email or password is incorrect.

import pymsl
user_auth_data = {
    'scheme': 'EMAIL_PASSWORD',
    'authdata': {
            'email': email, 
            'password': pwd,
        }
    }
client = pymsl.MslClient(user_auth_data)
client.load_manifest(80186674)

[feature request] implementation NF metadata API

Hi, is there a possibility that it will be implemented the https://www.netflix.com/api/shakti/v10733b56/metadata metadata api request in pymsl ? In order to get all the metada infos of a full show and all season/episode from a single link without having to use cookies or another auth outside pymsl.

Thanks

Error in retrieving manifest

Given this...

id = sys.argv[1]
user_auth_data = {
'scheme': 'EMAIL_PASSWORD',
'authdata': {
'email': '[email protected]',
'password': 'xxxxx'
}
}

client = pymsl.MslClient(user_auth_data) manif = client.load_manifest([id]) print manif

Runnig
python script.py 80249081
I get this weird error

pymsl.exceptions.ManifestError: {u'result': {u'errorDetails': u'This title is not available to watch instantly', u'errorDisplayMessage': u'This title is not available to watch instantly. Please try another title.', u'data': u'com.netflix.api.service.APILookupException: Reference: 80249081, Error Message : java.lang.String cannot be cast to java.lang.Integer', u'errorExternalCode': 50230418, u'errorSubCode': 1331}, u'success': False}

Is there any problem with it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.