# Fiddler Web Debugger

**URL:** <https://forums.plex.tv/t/fiddler-web-debugger/31805>\
**Category:** Dev/API Corner\
**Tags:** plugin-dev\
**Created:** [March 30, 2013, 11:00pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805 "2013-03-30T23:00:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![akickerz](https://avatars.discourse-cdn.com/v4/letter/a/8e8cbc/32.png) [@akickerz](https://forums.plex.tv/u/akickerz)\
**Post date:** [March 30, 2013, 11:00pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/1 "2013-03-30T23:00:50Z")

</div>

One of the tools I can't do without when I need to inspect http request/response messages in RAW/JSON/XML format is Fiddler 2.

&nbsp;

[http://www.fiddler2.com/fiddler2/](http://www.fiddler2.com/fiddler2/)

&nbsp;

Not sure if others use it as well...

&nbsp;

It inserts itself as a proxy between your pc and the web server allowing you to watch the traffic.

&nbsp;

![IC68965.gif](http://i.msdn.microsoft.com/dynimg/IC68965.gif)

&nbsp;

Another great feature is using it as a proxy for mobile devices so that you can examine their traffic to the target server as well. e.g. Enter the proxy setting on your wireless connection on your ipad and enable remote connections within fiddler and all http traffic from the ipad is now visible in the fiddler app on your pc (assuming they are both in the same subnet).

&nbsp;

Hope it helps others as it has helped me.

&nbsp;

---

<div class="post-metadata">

**Author:** ![Gerk](https://sea1.discourse-cdn.com/plex/user_avatar/forums.plex.tv/gerk/32/81980_2.png) [@Gerk](https://forums.plex.tv/u/Gerk)\
**Post date:** [April 2, 2013, 2:10am UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/2 "2013-04-02T02:10:09Z")

</div>

That looks pretty handy. &nbsp;I personally use Charles Proxy (and I know a couple of the other channel devs do as well) -- but it's not freeware.

---

<div class="post-metadata">

**Author:** ![akickerz](https://avatars.discourse-cdn.com/v4/letter/a/8e8cbc/32.png) [@akickerz](https://forums.plex.tv/u/akickerz)\
**Post date:** [April 2, 2013, 9:05am UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/3 "2013-04-02T09:05:06Z")

</div>

Some more on Fiddler...which I find very useful and here’s why…

[Note 1: the following information is from my own investigation and may not be entirely correct but works in part for me – take from it what you need]

[Note 2: The example from TVNZ is geo-locked for NZ so try with a site from your region]

[Note 3: Before doing any of the following steps Start Fiddler]

1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Take a content delivery network (CDN) such as Brightcove that is used by an on-demand provider such as [http://www.tvnz.co.nz/ondemand](http://www.tvnz.co.nz/ondemand) to host an rtmpe stream.

Via Google Chrome we can browse to a show which resolves to the friendly URL e.g. &nbsp;[http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240](http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240)

2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inspection of the HTTP Response to the page request above in Fiddler shows the following flash player object

http://images.tvnz.co.nz/brightcove/message/message.xml" name="localizedErrorXML"/\>

http://tvnz.co.nz/the-carrie-diaries/ s1-ep11-video-5389240" name="linkBaseURL"/\>

The key information here is:

swfURL = [http://admin.brightcove.com/viewer/us20130328.1037/BrightcoveBootloader.swf](http://admin.brightcove.com/viewer/us20130328.1037/BrightcoveBootloader.swf)

PlayerID = playerID=1029272630001

VideoPlayer = ref: 5389240

3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Immediately following this we see the outbound AMF request (which we need to mirror in our own code):

[http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001](http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001)

And this request is very important to dissect so that we can extract the rtmpe information.

From Fiddler we can see the browser request content (Fiddler: RAW http request view) which contains the BrightCove class references requiring instantiation in our own code:

- com.brightcove.experience.ViewerExperience
- com.brightcove.experience.ContentOverride

Our URL Service needs to extract the rtmpe FLVFullLengthURL which will look something like this:

Video\_URL: [u'rtmpe://cp133145.edgefcs.net/ondemand/', u'mp4:videos/963482467001/963482467001\_2250946345001\_5380974.mp4']

To do this we need to look closer at the http request [http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001](http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001)

Fiddler Hex http request view shows us the class properties above and most importantly the value population for each property. In our URL service code we can map this as follows:

class ContentOverride(object):

&nbsp;&nbsp;&nbsp; def \_\_init\_\_ (self, videoPlayer=None):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentType = int(0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentIds = None

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.target = None

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentId = None

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.featuredRefId = None

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;self.contentRefIds = None

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.featuredId = float('nan')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentRefId = videoPlayer ## ‘5389240’’

class ViewerExperienceRequest(object):

&nbsp;&nbsp;&nbsp; def \_\_init\_\_ (self, url=None, playerID=None, playerKey=None, video\_obj=None):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.experienceId = int(playerID) ## 1029272630001

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.playerKey = ''

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentOverrides = []

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.contentOverrides.append(video\_obj) ## the ContentOverride object

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.TTLToken = ''

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.URL = url &nbsp;## [http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240](http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.deliveryType = ''

4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Construct the URL Service code to extract the rtmpe including the above class definitions

#########################################################################################

def DoAmfRequest(url):

&nbsp;&nbsp;&nbsp; Log('Get Data From:::: '+url)

&nbsp;&nbsp;&nbsp; data = HTML.ElementFromURL(url).xpath('//object[@class="BrightcoveExperience "]')

&nbsp;&nbsp;&nbsp; if len(data) == 0:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log('No data')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return None

&nbsp;&nbsp;&nbsp; else:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data = data[0]

&nbsp;&nbsp;&nbsp; playerID = data.xpath('./param[@name="playerID"]')[0].get('value')

&nbsp;&nbsp;&nbsp; Log('PlayerID: '+playerID)

&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp; videoPlayer = data.xpath('./param[@name="@videoPlayer"]')[0].get('value').strip('ref:')

&nbsp;&nbsp;&nbsp; result = AmfRequest(url=url, playerID=playerID, playerKey=playerID, videoPlayer=videoPlayer)

&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp; return result

#########################################################################################

def AmfRequest(url=None, playerID=None, playerKey=None, videoPlayer=None):

&nbsp;&nbsp;&nbsp; endpoint = AMF\_URL ##&nbsp;[http://c.brightcove.com/services/messagebroker/amf](http://c.brightcove.com/services/messagebroker/amf)

&nbsp;&nbsp;&nbsp; if playerKey:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endpoint += '?playerId=%s' % playerKey

&nbsp;&nbsp;&nbsp; client = AMF.RemotingService(url=endpoint, user\_agent='', amf\_version=3)

&nbsp;&nbsp;&nbsp; service = client.getService('com.brightcove.experience.ExperienceRuntimeFacade')

&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp; AMF.RegisterClass(ContentOverride, 'com.brightcove.experience.ContentOverride')

&nbsp;&nbsp;&nbsp; AMF.RegisterClass(ViewerExperienceRequest, 'com.brightcove.experience.ViewerExperienceRequest')

&nbsp;&nbsp;&nbsp; video\_obj = ContentOverride(videoPlayer)

&nbsp;&nbsp;&nbsp; experience = ViewerExperienceRequest(url, playerID, playerKey, video\_obj)

&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp; try:

&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;result = service.getDataForExperience('', experience)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log(result.items())

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result['programmedContent']['videoPlayer']['mediaDTO']

&nbsp;&nbsp;&nbsp; except:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log('Exception in AMF Request')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise Ex.MediaGeoblocked

The request to the service returns the full metadata associated with the media in the result var

result = service.getDataForExperience('', experience)

From the result we can now grab the FLVFullLengthURL along with a number of other useful properties:

[u'rtmpe://cp133145.edgefcs.net/ondemand/', u'mp4:videos/963482467001/963482467001\_2250946345001\_5380974.mp4']

Now using the downloadable app rtmpDump.exe ([http://rtmpdump.mplayerhq.hu/](http://rtmpdump.mplayerhq.hu/)) we can confirm the stream by downloading the file and saving out as a flash player video (flv) which can be played using a video player such as VLC ([http://www.videolan.org/vlc/download-windows.html](http://www.videolan.org/vlc/download-windows.html))

Rtmpdump.exe -r "rtmpe://cp133145.edgefcs.net/ondemand/" -a "ondemand" -y "mp4:videos/963482467001/963482467001\_2250946345001\_5380974.mp4" -o myVideo.flv

5.&nbsp; The final stage is to have Plex play the stream

This is actually the point in my current project which is not working yet but the theory is that the rtmpe is passed back in the callback from your plex playVideo method via RTMPVideoURL

IndirectResponse(VideoClipObject, key=RTMPVideoURL(url=player, clip=playpath, app='ondemand', swf\_url=SWF\_URL, args=[False, playpath]))

Enabling rtmp in the info.plist and serviceinfo.plist is essential with the following addition to both files:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlexFrameworkFlags

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UseRealRTMP

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

6.&nbsp; Monitoring the logs

For the URL service I watch the log file:

%LocalAppData%\Plex Media Server\Logs\PMS Plugin Logs\ com.plexapp.system.log

2013-04-02 21:32:58,650 (1b60) :&nbsp; DEBUG (context:198) - Checking for Real RTMP support...&nbsp; Enabled:True&nbsp; Platform:Chrome&nbsp; Product:Web Client&nbsp; Client:0.9.9.13&nbsp; Server:0.9.7.19-3baac57

2013-04-02 21:32:58,651 (1b60) :&nbsp; DEBUG (objectkit:754) - Using Real RTMP

2013-04-02 21:32:58,654 (1b60) :&nbsp; DEBUG (runtime:106) - Sending packed state data (99 bytes)

2013-04-02 21:32:58,654 (1b60) :&nbsp; DEBUG (runtime:896) - Response: [200] MediaContainer, 1270 bytes

… and this is where it all stops for me… the video&nbsp;doesn't&nbsp;play from the browser or the windows client for some reason :(

Ok...fixed...playing in clients now...I missed specifying the rtmp protocol

def MediaObjectsForURL(url):

&nbsp; &nbsp; return [

&nbsp; &nbsp; &nbsp; MediaObject(

&nbsp; &nbsp; &nbsp; &nbsp; video\_codec = VideoCodec.H264,

&nbsp; &nbsp; &nbsp; &nbsp; audio\_codec = AudioCodec.AAC,

&nbsp; &nbsp; &nbsp; &nbsp; container = Container.MP4,

&nbsp; &nbsp; &nbsp; &nbsp; protocol='rtmp',

&nbsp; &nbsp; &nbsp; &nbsp; parts = [PartObject(key=Callback(PlayVideo, url = url))],

&nbsp; &nbsp; &nbsp; &nbsp; audio\_channels = 2,

&nbsp; &nbsp; &nbsp; &nbsp; optimized\_for\_streaming = True

&nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; ]

---

<div class="post-metadata">

**Author:** ![psycik](https://avatars.discourse-cdn.com/v4/letter/p/b77776/32.png) [@psycik](https://forums.plex.tv/u/psycik)\
**Post date:** [April 14, 2013, 7:46pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/4 "2013-04-14T19:46:19Z")

</div>

HI, did you use this information as the basis of a tvnz plugin?&nbsp; Wondering if things have changed now they've gone brightcove and/or released an ios app.

---

<div class="post-metadata">

**Author:** ![akickerz](https://avatars.discourse-cdn.com/v4/letter/a/8e8cbc/32.png) [@akickerz](https://forums.plex.tv/u/akickerz)\
**Post date:** [April 18, 2013, 6:54am UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/5 "2013-04-18T06:54:40Z")

</div>

Yes, it was for&nbsp;tvnz.co.nz/ondemand where they are serving content from the Brightcove service.

I have one issue where the rtmp feed stops playing after 2 mins and I have to press play again. Not sure why this is happening.

---

<div class="post-metadata">

**Author:** ![mattnz](https://sea1.discourse-cdn.com/plex/user_avatar/forums.plex.tv/mattnz/32/81926_2.png) [@mattnz](https://forums.plex.tv/u/mattnz)\
**Post date:** [April 20, 2013, 7:51pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/6 "2013-04-20T19:51:55Z")

</div>

I was wondering if you had solved the feed stopping issue please?&nbsp; I'm using the TVNZ Bundle that Ian developed and the playback stops after about 90-120 seconds

---

<div class="post-metadata">

**Author:** ![psycik](https://avatars.discourse-cdn.com/v4/letter/p/b77776/32.png) [@psycik](https://forums.plex.tv/u/psycik)\
**Post date:** [April 20, 2013, 9:34pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/7 "2013-04-20T21:34:05Z")

</div>

Is there a full bundle for this that can be downloaded?

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/plex/original/3X/2/a/2acb9765406f63293d357b4ec509ec39aa28f2ad.png) [@system](https://forums.plex.tv/u/system)\
**Post date:** [December 20, 2019, 11:08pm UTC](https://forums.plex.tv/t/fiddler-web-debugger/31805/8 "2019-12-20T23:08:32Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
