Decode Base64 Angular: Encoding and Decoding in Angular Apps

Angular has no Base64 helper of its own; you use the browser APIs. What Angular adds is a sanitizer, and it cares much more about where a decoded file is displayed than about the Base64 itself.

Encoding and decoding

The browser built-ins work as usual, wrapped in a service for reuse. Handle Unicode explicitly, since btoa throws above U+00FF:

@Injectable({ providedIn: 'root' })
export class Base64Service {
  encode(value: string): string {
    return btoa(String.fromCharCode(...new TextEncoder().encode(value)));
  }

  decode(value: string): string {
    return new TextDecoder().decode(
      Uint8Array.from(atob(value), (c) => c.charCodeAt(0))
    );
  }
}

The sanitizer

Current Angular versions strip only javascript: URLs from [src] and [href] bindings, so <img [src]="'data:image/png;base64,' + b64"> renders without any help. Many tutorials, written for older releases, still wrap image data URIs like this:

constructor(private sanitizer: DomSanitizer) {}

imageUrl(b64: string): SafeUrl {
  return this.sanitizer.bypassSecurityTrustUrl(
    'data:image/png;base64,' + b64
  );
}

Where a bypass is genuinely needed is a resource URL. Binding a decoded PDF to <iframe [src]> or <object [data]> fails with "unsafe value used in a resource URL context" until the value goes through bypassSecurityTrustResourceUrl. Both bypass methods switch off Angular's XSS protection for that value, so never pass user-supplied strings through them: a data:text/html payload in an iframe is executable markup.

Decoding a JWT payload

JWT segments are base64url, so translate the alphabet and restore padding before decoding:

decodeJwtPayload(token: string): unknown {
  const part = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
  const padded = part.padEnd(part.length + ((4 - (part.length % 4)) % 4), '=');
  return JSON.parse(this.decode(padded));
}

This reads the claims; it does not verify the signature. Never make an authorisation decision in the browser based on a decoded token — the server must verify it.

Frequently asked questions

Why is my Base64 image or PDF blank?

For images it is rarely the sanitizer, which lets `data:image/…` URLs through; check that the MIME type matches the file and that the string was not cut off. A PDF in an iframe does need `bypassSecurityTrustResourceUrl`, and only for values your app generated.

Do I need a Base64 npm package?

No. atob and btoa cover it; add a TextEncoder step for Unicode.

Is decoding a JWT in Angular safe?

Reading claims for display is fine. Trusting them for access control is not — only the server can verify the signature.