Is picture in picture safe?
Picture in Picture is critical risk. Every time you navigate, the extension sends the URL's origin and path to backend.pictureinpic.com. Capture confirmed five POSTs with the visited URL. The stated purpose, picture-in-picture video, does not require sending every URL visited.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
PiP Extension Reports Every Page You Visit to Its Own Server
Every time you navigate, the extension sends the URL's origin and path to backend.pictureinpic.com.
Capture confirmed five POSTs with the visited URL.
The stated purpose, picture-in-picture video, does not require sending every URL visited.
You navigate to any page in any tab.
The extension immediately POSTs the page's origin and path to its own backend server.
Fires automatically with no user interaction. Covers every site, not just video pages.
| Content-Type | application/json |
{
"uri": "https://en.wikipedia.org/wiki/Picture-in-picture"
}| Field | Value | Why it matters | |
|---|---|---|---|
Page origin and path | https://en.wikipedia.org/wiki/Picture-in-picture | The site and page you are viewing, enough to reconstruct your browsing activity across all sites. |
The navigation listener in background.js (lines 55-98):
// Fires every time any tab finishes loading.
// For every completed navigation, constructs the page origin + path
// and POSTs it as JSON to the extension's backend.
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status !== 'complete') return;
const pageUrl = new URL(tab.url);
const uri = pageUrl.origin + pageUrl.pathname; // e.g. "https://example.com/path"
fetch('https://backend.pictureinpic.com/api/video-selector', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ uri })
})
.then(res => res.json())
.then(g => {
// Server may return CSS selectors to inject into the page
if (g.val['cselector']) fetchAndInject(g.val['cselector'], tabId);
if (g.val['dselector']) fetchUrl(g.val['dselector']);
});
});- backend.pictureinpic.com
Backend server run by the Picture in Picture developer. Receives the origin+pathname of every page visited and returns CSS selectors for optional content injection.
Intercepts the fetch() call in the extension's service worker and logs every URL reported to backend.pictureinpic.com as you browse.
// pip-navigation-monitor.js
// Run this in Chrome DevTools on the service worker for the Picture in Picture extension.
// Open chrome://extensions, enable Developer mode, find the extension, click
// the 'service worker' link to open its DevTools, then paste this into the console.
(function () {
const originalFetch = self.fetch.bind(self);
self.fetch = function (url, options) {
if (typeof url === 'string' && url.includes('backend.pictureinpic.com/api/video-selector')) {
let body = '(no body)';
try {
body = options && options.body ? options.body : '(no body)';
} catch (e) {}
console.log('[PIP_MONITOR] Navigation reported:', url);
console.log('[PIP_MONITOR] Request body:', body);
}
return originalFetch(url, options);
};
console.log('[PIP_MONITOR] Installed. Navigate to any page to see reported URLs.');
})();
- 1Install Picture in Picture.
- 2Open chrome://extensions, enable Developer mode.
- 3Open the service worker DevTools console.
- 4Paste this script, press Enter.
- 5Visit any page; navigation logs the URL sent to backend.pictureinpic.com.