Is UnTrap for YouTube — Block Shorts, Remove Recommendations, Detox & Focus safe?
UnTrap is medium risk. Using transcript summarization on a YouTube watch page builds a request with the video URL, a stored user ID, language, date, and initial-request flag, posted to untrap.app. Traced from shipped code; an earlier run captured no live body.
Who publishes ityevhen.tretiakov - 1 other listing from the same operator, none carrying a finding
yevhen.tretiakov - 1 other listing from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
1 other listing published from this account, 70k+ users between them, none of them carrying a finding.
Shared hosts - 1 hostname
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
YouTube video URL sent for transcription summaries
Using transcript summarization on a YouTube watch page builds a request with the video URL, a stored user ID, language, date, and initial-request flag, posted to untrap.app.
Traced from shipped code; an earlier run captured no live body.
You ask the extension to summarize a YouTube video's transcript.
The request path runs when the transcript tab is selected or the summary panel generates transcript content.
The extension prepares a JSON request with the current video URL and your stored identifier.
The request is addressed to untrap.app's transcription summarization API.
| Field | Value | Why it matters | |
|---|---|---|---|
Current YouTube video | https://www.youtube.com/watch?v=dQw4w9WgXcQ (illustrative) | Shows which video you asked the service to summarize. | |
Stored user identifier | b6f2d8c1-3a10-4e1f-90d6-5b2c6b7e2a41 (illustrative) | Lets the service associate the summary request with the same extension user record across requests. | |
Summary language | English | Tells the service which language to use for the transcript summary. | |
Request date | 2026-07-14 (illustrative) | Adds the day when the summary request was made. | |
Initial request flag | true | Indicates whether this is the first transcript summary request for the current video view. |
| Content-Type | application/json |
The transcript summary request body and POST sender
function generateTranslateVideoSummary(tabItem) {
storageService
.get([getConstNotSyncing.notSyncingState, getConst.system])
.then(async (result) => {
const notSyncingState = result[getConstNotSyncing.notSyncingState] ?? {};
const systemState = result[getConst.system] ?? {};
const sharedState = systemState[getConst.sharedState] ?? {};
const summarizeWindowState =
systemState[getConst.summarizeWindowState] ?? {};
const languageToTranslate =
summarizeWindowState[getConst.transcriptTranslateLanguage] ?? "English";
const userEmail =
notSyncingState[getConstNotSyncing.pro_usernameData] ?? "";
const userIdentifier = sharedState[getConst.userUniqueIdentifier] ?? "";
const currentDate = getRequestDate();
const currentHref = window.location.href;
const videoSummarizeWindowContainer = document.getElementById(
"videoSummarizeWindowContainer",
);
if (videoSummarizeWindowContainer) {
const videoSummarizeContainer =
videoSummarizeWindowContainer.querySelector("#contentContainer");
transcriptionAbortController = new AbortController();
try {
const translate = await summarizeService.summarizeRequest({
body: {
url: currentHref,
language: languageToTranslate,
user_identifier: userIdentifier,
request_date: currentDate,
is_initial: true,
},
controller: transcriptionAbortController,
fetchUrl: _ENDPOINTS.summarize.translate,
});
if (videoSummarizeContainer) {
copiedSummaryText.transcripts += "";
copiedSummaryText.transcripts += `${getVideoName()}\n\n`;
if (tabItem && tabItem.hasAttribute("select")) {
videoSummarizeContainer.innerHTML = "";
const parsedTranscriptionHtml = parseAndGenerateTranscriptionHTML(
translate.translated_chunk,
translate.chunk_limit_exceed,
false,
);
const purifyParsedTranscriptionHtml = DOMPurify.sanitize(
parsedTranscriptionHtml,
);
videoSummarizeContainer.innerHTML = purifyParsedTranscriptionHtml;
}
htmlContentState.transcripts = parseAndGenerateTranscriptionHTML(
translate.translated_chunk,
translate.chunk_limit_exceed,
true,
);
copyButtonDisabledHandler();
transcriptionAbortController = undefined;
loadMoreTranslate(videoSummarizeContainer, currentHref);
}
} catch (error) {
transcriptionAbortController = undefined;
if (error.message !== "signal is aborted without reason") {
if (videoSummarizeContainer) {
if (tabItem && tabItem.hasAttribute("select"))
if (error.message === `You’ve reached the daily limit`) {
videoSummarizeContainer.innerHTML = getFreeQuotaReachedHtml(
userEmail,
userIdentifier,
);
} else if (
error.message ===
"You have reached your free request limit. To continue using the summarize feature, please upgrade to Plus plan"
) {
videoSummarizeContainer.innerHTML = getFreeQuotaReachedHtml(
userEmail,
userIdentifier,
error.message,
);
} else if (error.message === "Transcript not found") {
getCustomErrorHtml(videoSummarizeContainer, error.message);
} else if (error.message === "Too many requests") {
getCustomErrorHtml(
videoSummarizeContainer,
"Too many requests. Please try again later",
() => generateTranslateVideoSummary(tabItem),
);
} else {
getCustomErrorHtml(
videoSummarizeContainer,
"Something went wrong.",
() => generateTranslateVideoSummary(tabItem),
);
}
}
}
}
}
});
}async function summarizeFetchFunction(
body,
controller,
fetchUrl,
timeoutMs = 60_000,
) {
const id = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(fetchUrl, {
method: "POST",
signal: controller.signal,
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.json();
throw new Error(`${errorText.error}`);
}
const data = await response.json();
return data;
} catch (err) {
if (err.name === "AbortError") {
throw new Error("Request timed out");
}
throw err;
} finally {
clearTimeout(id);
}
}const _ENDPOINTS = {
auth: {
login: "https://untrap.app/db/untrap/login.php",
signup: "https://untrap.app/db/untrap/signup.php",
updatePassword: "https://untrap.app/db/untrap/updatePass.php",
sendVerificationCode:
"https://untrap.app/api/untrap/send_verification_code",
verifyCode: "https://untrap.app/api/untrap/verify_code",
forgotPassword: "https://untrap.app/api/untrap/forgot-password",
deleteUser: "https://untrap.app/api/untrap/delete_user",
getUser: "https://untrap.app/api/untrap/get_user",
},
sync: {
updateFields: "https://untrap.app/db/untrap/updateFields.php",
fetchFields: "https://untrap.app/db/untrap/fetchFields.php",
},
settings: {
getAll: "https://untrap.app/api/untrap/get_settings",
getPartial: "https://untrap.app/api/untrap/get_partial_settings",
},
summarize: {
checkLimit: "https://untrap.app/api/check_request_limit",
insight: "https://untrap.app/api/summarize/insight",
timestamp: "https://untrap.app/api/summarize/timestamp",
comments: "https://untrap.app/api/summarize/comments",
translate: "https://untrap.app/api/summarize/transcription",
},
};- untrap.app
Receives the transcript summarization POST containing the current YouTube URL and request metadata.