Migrating Off Widevine CLS Before the 2027 Shutdown
Google switches off the free Widevine Cloud License Service on 13 April 2027. A second date, two months earlier and unverified, may decide whether your encrypted library survives at all. What to check this week, what the alternatives cost, and which part of the work eats the calendar.

Google is switching off a service that hundreds of streaming platforms run on, and I could not find an announcement to link you to.
I went looking properly. No blog post, no deprecation notice, no changelog entry. The date sits in the frequently asked questions on the Widevine training page, one sentence long: "The Widevine Cloud License Service will cease operations on April 13, 2027." That is it. Everything else you will read about this, including this post, is somebody reading that sentence and working out what it means.
The date that is real
The sentence above is from Widevine's own training page, and the same date is repeated by castLabs, Axinom, EZDRM, Nagra and Viaccess Orca. Treat it as fixed.
The service has been free, with no service level agreement and no support, which is precisely why so many platforms are on it. Somebody wired it in during a proof of concept, it worked, and nobody revisited it.
Widevine itself is not going anywhere. castLabs says so explicitly, and it is worth repeating, because the first reaction in the room is always that Widevine is dead. Only the Google hosted endpoint retires. The client library and the device ecosystem carry on.
What breaks on 14 April 2027 is a licence request. Your player asks for a licence, receives nothing, shows an error. Every Widevine device, every title, at the same moment.
The date I could not verify
A post about deadlines that gets a deadline wrong is worthless, so here is where the ground goes soft.
castLabs' migration post says Google plans to disable the getcontentkey API in February 2027. If that is right, it matters more than April does.
I could not confirm it. I checked Google's own Widevine developer overview, which says nothing about any of this, and the training page that carries the April sentence, which says nothing about February. Then the migration posts from Axinom, EZDRM, Nagra, Viaccess Orca and Streaming Media. Every one of them gives April. Not one gives February, and not one mentions getcontentkey at all. The Hacker News thread has nobody claiming to have received a notice directly.
castLabs are a Google Widevine partner and may well know something I cannot see. So plan for February, and confirm it in writing with your Widevine contact this month. Do not take my word for the date, and do not take theirs. Ask.
Why it outranks April: the April date breaks playback, and playback can be repaired after the fact, painfully and in public but repaired. The February date is different in kind.
Losing the endpoint costs you a migration. Losing the keys costs you your library.
Triage: whose keys are they
Case one. You hold your content encryption keys, because you either generated them yourself or captured what Google generated. Nothing to rescue.
Case two. Google generated them and you never stored them. Your packager asked for a key by content id, encrypted with what came back, and discarded it, on the reasonable assumption that asking again returns the same key. It does, right up until the API goes. Then your encrypted library is a pile of files nobody can decrypt.
Which case are you in
The second question decides it. The first only tells you who made the keys.
Search your packager configuration for license.widevine.com/cenc/getcontentkey. If your encoder talks to that host, Google minted the keys. Then find where they landed, if anywhere: Shaka Packager's Widevine encryption fetches a key and uses it, and does not persist a key store unless somebody built one.
Then run the real test. Pick a title encoded in 2021 and produce its content encryption key from your own systems with the network to Google cut. If you cannot, you are in case two, and the export below is the most urgent thing on your board.
Exporting the keys
Same API your packager already uses, so the credentials exist somewhere in your encoding stack.
import { createHash, createCipheriv } from "node:crypto";
// This request shape is read from Shaka Packager's documentation and from open
// source clients, not from a Google specification I can link you to. Verify it
// against your own Widevine documentation before relying on it.
interface ContentKeyRequest {
content_id: string; // base64 of your content id
tracks: { type: string }[]; // "SD", "HD", "AUDIO"
drm_types: string[]; // ["WIDEVINE"]
policy: string;
}
// SHA1 the payload, encrypt the digest with your provider key under AES CBC.
// Also read from open source clients. Flagged, not confirmed.
const sign = (payload: string, key: Buffer, iv: Buffer): string => {
const digest = createHash("sha1").update(payload).digest();
const cipher = createCipheriv("aes-256-cbc", key, iv);
return Buffer.concat([cipher.update(digest), cipher.final()]).toString("base64");
};
export const exportKeys = async (
contentId: string,
provider: string,
key: Buffer,
iv: Buffer,
): Promise<unknown> => {
const request: ContentKeyRequest = {
content_id: Buffer.from(contentId).toString("base64"),
tracks: [{ type: "SD" }, { type: "HD" }, { type: "AUDIO" }],
drm_types: ["WIDEVINE"],
policy: "",
};
const payload = JSON.stringify(request);
const response = await fetch(
`https://license.widevine.com/cenc/getcontentkey/${provider}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
request: Buffer.from(payload).toString("base64"),
signature: sign(payload, key, iv),
signer: provider,
}),
},
);
return response.json();
};Run it over every content id in your catalogue, write the results somewhere you control and back up, and only then start thinking about vendors. Rate limits on that endpoint are not documented anywhere I can point you at, so build the loop to resume.
Where to go instead
A third party licence service
Four names come up: EZDRM, castLabs DRMtoday, Axinom and DoveRunner. All four have published a migration pitch, which tells you how much of their addressable market has just been handed to them. They meter one of two ways, and the choice matters more than the headline number.
Per licence issued. You pay each time a player asks for a key. castLabs DRMtoday publishes $299 a month covering the first 20,000 licence requests, then blocks of 1,000 sliding from $5 down to $1 as volume grows. EZDRM publishes Widevine Modular at $99.99 a month plus a $99.99 setup fee for 10,000 licences, and asks you to call above 20,000 licences or 2,000 users.
Per monthly active user. You pay per human rather than per request. DoveRunner meters this way, from $299 for the first 1,000 users then roughly $0.06 a user to 10,000. Axinom will bill either way, entry tier 199 euro covering 100,000 licences or 2,000 active users.
Those are published list prices in August 2026, so treat them as the shape rather than the quote. The useful work is one number: licences issued per active user last month. A catch up service where one viewer watches thirty episodes issues a lot of licences per person, and monthly active users wins. A live event issuing one licence per session is the other way round. Get that ratio before you take any quote seriously. Integration itself is the small part: you get an endpoint and a credential.
Self hosting the License Server SDK
Google will license you the License Server software development kit to run yourself, with no per licence fee. The gate is the Certified Widevine Implementation Partner programme, whose requirements are published on the training page: two certified members of staff minimum, annual fees to stay in good standing, three days of class and lab training, an exam needing 90 per cent and completed within 30 days, and audits of end user sites.
The annual fee is not published. Neither are the licence terms for the kit itself.
So I cannot give you a break even point, and I would not trust the published ones either. Two write ups from June 2026 put the crossover at "roughly 5M+ licenses per month" and at "between 500,000 and 1,000,000 monthly license requests". They differ by a factor of ten, both were written by companies selling the managed alternative, and neither of them prices the certification, which is the part you cannot opt out of.
As a judgement, labelled as one: the cost is not the licence, it is two engineers who must stay certified plus a service that cannot be down at eight on a Saturday night. Compare that against your vendor bill, not against zero. For most platforms it sits a long way up.
The part that eats the calendar
Repointing the proxy is an afternoon.
// Before: the proxy forwarded the licence challenge to Google's free service.
// After: it forwards to the vendor, and now has to say who the viewer is.
const LICENCE_URL = process.env.LICENCE_URL!;
const VENDOR_AUTH_HEADER = process.env.VENDOR_AUTH_HEADER!;
export const proxyLicenceRequest = async (
challenge: ArrayBuffer,
entitlement: Entitlement,
): Promise<ArrayBuffer> => {
const response = await fetch(LICENCE_URL, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
// Header name and token format are vendor specific. Read their docs
// rather than copying this.
[VENDOR_AUTH_HEADER]: await signEntitlement(entitlement),
},
body: challenge,
});
if (!response.ok) throw new Error(`licence request failed: ${response.status}`);
return response.arrayBuffer();
};The interesting change is that second header. Whatever your proxy does today to decide this viewer may watch this title, the vendor now needs telling, as a signed token carrying the entitlement and the policy. That is a change to your authorisation path, not a configuration edit, and it is the piece most likely to be under tested, because it works fine for the account you are logged in as.
New content flows through the Content Protection Information Exchange Format, the DASH Industry Forum standard for handing keys between a packager and a licence server, or through Amazon's profile of it, Secure Packager and Encoder Key Exchange. Version 1 of that profile builds on version 2.0 of the exchange format and version 2 on version 2.3, so if you run AWS Elemental packaging, ask your vendor which version they speak. Your back catalogue is a separate job: a bulk import of the keys you rescued.
Then the device matrix, which is where the time actually goes. Chrome with Encrypted Media Extensions works on the second afternoon and gives everybody false confidence. Android through ExoPlayer needs testing across the API levels you support and both security levels, because hardware backed and software only devices stop behaving identically once policy is involved. Smart televisions are the ones that hurt: Samsung Tizen, LG webOS and whatever set top boxes you ship, on firmware that will never be updated again and that you cannot debug remotely.
What you are looking for there is policy drift. Licence duration, offline playback and output protection defaults on the new vendor will not match whatever the free service handed out. A title that plays on your desk and refuses on a five year old television is usually a policy difference, not a broken integration.
A realistic timeline
My estimate from the shape of the work, not a measurement.
Two weeks of triage, answering the key question and inventorying every application and device family in production. Two to four weeks of key export if you are in case two, running first regardless of what else is on the list. Two to three weeks of vendor selection. Three to four weeks of integration in staging. Six to ten weeks of device testing and firmware chasing. Two to four weeks of staged rollout by device family, old path still live behind a flag.
Call it four to seven months elapsed for a platform of any size. Elapsed, not effort, because half of it is waiting on a device partner, a certification queue or an application store review.
Which is why starting after summer 2026 is tight. If your keys are Google's, work back from February rather than April, on the assumption that the date I could not verify is real. Being early costs you nothing. From September that is five months, and you do not get all five. Nobody ships digital rights management changes through December, and nobody ships them in the run up to a live rights event they hold. Two of the five are already spoken for.
What I have not checked
The February date and the shutdown of getcontentkey. One source, confirmed by nothing and contradicted by nothing, and the most important thing on this page to check for yourself. I looked for it in nine other places, two of them Google's own, and found it in none.
The signature construction in the export snippet, read from open source clients rather than a Google specification. Consistent across several independent implementations, which is reassuring and is not the same as documented.
The prices, which are list prices from vendors with every incentive to discount hard for anyone arriving from the free service. Ask for the migration rate.
And I have not run this end to end against any of the four. If you have pulled a large catalogue through that API, I want to hear what it did at volume.
I do this kind of migration work as a contractor, so if you are staring at a library whose keys you cannot produce, that is the sort of thing I take on.
Questions about the build, or building something similar? Say hello. I read every message.