Web APIs Cheatsheet

Clipboard and File API

Use this Web APIs reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Clipboard API (Async)

Requires HTTPS and clipboard-read/clipboard-write permissions.

// Write text
await navigator.clipboard.writeText('Hello, clipboard!');

// Read text
const text = await navigator.clipboard.readText();

// Write multiple items / rich content
await navigator.clipboard.write([
  new ClipboardItem({
    'text/plain': new Blob(['plain text'], { type: 'text/plain' }),
    'text/html': new Blob(['<b>bold</b>'], { type: 'text/html' }),
    'image/png': imageBlob,
  }),
]);

// Read clipboard items
const items = await navigator.clipboard.read();
for (const item of items) {
  item.types;                           // ['text/plain', 'image/png']
  if (item.types.includes('image/png')) {
    const blob = await item.getType('image/png');
    const url = URL.createObjectURL(blob);
  }
}

Permission Check

const write = await navigator.permissions.query({ name: 'clipboard-write' });
const read  = await navigator.permissions.query({ name: 'clipboard-read' });
write.state; // 'granted' | 'denied' | 'prompt'

Clipboard Events (Legacy)

// copy — fires on Ctrl+C / Cmd+C
document.addEventListener('copy', e => {
  const selection = window.getSelection()?.toString();
  e.clipboardData.setData('text/plain', selection + '\n— example.com');
  e.clipboardData.setData('text/html', `<p>${selection}</p>`);
  e.preventDefault(); // suppress default copy
});

// cut
document.addEventListener('cut', e => {
  e.clipboardData.setData('text/plain', selectedText);
  deleteSelection();
  e.preventDefault();
});

// paste
document.addEventListener('paste', e => {
  const text = e.clipboardData.getData('text/plain');
  const html  = e.clipboardData.getData('text/html');
  // Files pasted from OS
  const files = [...e.clipboardData.files];
  e.preventDefault();
});

ClipboardEvent.clipboardData Methods

MethodDescription
.getData(type)Returns string for the given MIME type
.setData(type, data)Set data for MIME type (only inside copy/cut handler)
.clearData(type?)Clear one or all types
.filesFileList of pasted files
.itemsDataTransferItemList
.typesArray of available MIME type strings

DataTransfer and DataTransferItem

// Also used in drag events (e.dataTransfer)
const dt = e.clipboardData; // DataTransfer

for (const item of dt.items) {
  item.kind;    // 'string' | 'file'
  item.type;    // MIME type string

  if (item.kind === 'string') {
    item.getAsString(str => console.log(str));
  }
  if (item.kind === 'file') {
    const file = item.getAsFile(); // File object
  }
}

File API

File and Blob

Property / MethodTypeDescription
file.namestringOriginal filename
file.sizenumberSize in bytes
file.typestringMIME type (empty if unknown)
file.lastModifiednumberms since epoch
file.lastModifiedDateDateDeprecated
file.text()Promise\<string\>Read as UTF-8 text
file.arrayBuffer()Promise\<ArrayBuffer\>Read as binary
file.stream()ReadableStreamStreaming read
file.slice(start?, end?, type?)BlobSlice a byte range
// File inherits from Blob
const blob = new Blob(['hello'], { type: 'text/plain' });
const file = new File([blob, ' world'], 'hello.txt', { type: 'text/plain', lastModified: Date.now() });

// Slice large files for chunked upload
function* chunkFile(file, chunkSize = 1024 * 1024) {
  let offset = 0;
  while (offset < file.size) {
    yield file.slice(offset, offset + chunkSize);
    offset += chunkSize;
  }
}

FileReader (event-based, legacy)

const reader = new FileReader();

reader.readAsText(file, 'utf-8');
reader.readAsDataURL(file);          // base64 data: URL
reader.readAsArrayBuffer(file);
reader.readAsBinaryString(file);     // Deprecated

reader.onload = e => {
  e.target.result;  // string | ArrayBuffer
};
reader.onprogress = e => {
  e.loaded; e.total; e.lengthComputable;
};
reader.onerror = e => e.target.error;  // DOMException
reader.onabort = e => {};
reader.abort();

reader.readyState; // 0=EMPTY, 1=LOADING, 2=DONE
reader.result;     // after load: string | ArrayBuffer | null

Modern File Reading (Promise-based)

// Prefer these over FileReader
const text   = await file.text();
const buffer = await file.arrayBuffer();
const stream = file.stream();          // ReadableStream<Uint8Array>

// Stream processing
const reader = file.stream().getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  process(value); // Uint8Array chunk
}

Object URLs

const url = URL.createObjectURL(file);  // blob:... URL, in-memory
img.src = url;                          // use immediately

// IMPORTANT: release when done to free memory
URL.revokeObjectURL(url);

// Revoke after load
img.onload = () => URL.revokeObjectURL(url);

File System Access API (modern, browser-only)

Open Files

// Single file
const [handle] = await window.showOpenFilePicker({
  multiple: false,
  types: [{ description: 'Images', accept: { 'image/*': ['.png', '.jpg', '.webp'] } }],
  excludeAcceptAllOption: false,
  startIn: 'pictures', // 'desktop' | 'documents' | 'downloads' | 'music' | 'pictures' | 'videos'
});

const file = await handle.getFile();
const text = await file.text();

// Multiple files
const handles = await window.showOpenFilePicker({ multiple: true });

Save Files

const handle = await window.showSaveFilePicker({
  suggestedName: 'data.json',
  types: [{ description: 'JSON', accept: { 'application/json': ['.json'] } }],
});

const writable = await handle.createWritable();
await writable.write('{"hello": "world"}');
await writable.write(new Blob([data]));
await writable.write({ type: 'write', data, position: 0 });  // write at offset
await writable.write({ type: 'seek', position: 10 });         // seek
await writable.write({ type: 'truncate', size: 100 });        // resize
await writable.close();

Directory Picker

const dirHandle = await window.showDirectoryPicker({
  id: 'project-folder',
  mode: 'readwrite', // 'read' | 'readwrite'
});

// List files
for await (const [name, handle] of dirHandle) {
  handle.kind; // 'file' | 'directory'
  handle.name;
}

// Get file in directory
const fileHandle = await dirHandle.getFileHandle('README.md');
const subDir     = await dirHandle.getDirectoryHandle('src', { create: true });
await dirHandle.removeEntry('old-file.txt', { recursive: false });

// File handle methods
handle.kind;   // 'file'
handle.name;   // 'README.md'
await handle.isSameEntry(otherHandle);
await handle.queryPermission({ mode: 'readwrite' }); // 'granted' | 'denied' | 'prompt'
await handle.requestPermission({ mode: 'readwrite' });

Persist Handle Across Sessions (with IndexedDB)

// Store handle in IDB — permissions may need re-requesting on next visit
import { set, get } from 'idb-keyval';
await set('last-file', fileHandle);
const restored = await get('last-file');
// Re-request permission
if (await restored.queryPermission({ mode: 'readwrite' }) !== 'granted') {
  await restored.requestPermission({ mode: 'readwrite' });
}

File Input Programmatic Tricks

const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.multiple = true;
input.addEventListener('change', () => {
  const files = [...input.files];
});
input.click(); // trigger picker without user clicking an element

// Drag-and-drop file entry
dropZone.addEventListener('drop', async e => {
  e.preventDefault();
  for (const item of e.dataTransfer.items) {
    if (item.kind === 'file') {
      const file = item.getAsFile();
      // or FileSystem API entry
      const entry = item.webkitGetAsEntry();
      if (entry.isDirectory) readDir(entry);
    }
  }
});