Google Fonts WOFF2 Downloader

This tool allows you to download Google Fonts WOFF2 files directly from a Google Fonts embed link.

Simply paste your Google Fonts embed link in the input field below and click the “Fetch Fonts” button.

The tool will retrieve the CSS, extract the font-face declarations, and display a download link for each font.

Click on the “Download .woff2” button next to a font to download it with a properly generated file name.

Example URL https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap

Enter an embed link and click “Fetch Fonts”.

How it works;

<div class="container">
  <div class="input-container">
    <input type="text" id="embedLink"  
           placeholder="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
    <button id="fetchBtn">Fetch Fonts</button>
  </div>
  <div id="resultContainer">Enter an embed link and click "Fetch Fonts".</div>
</div>

<script>
  // Function to download file using blob so that we can force the file name.
  async function downloadFile(url, fileName) {
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Network response was not ok');
      const blob = await response.blob();
      const blobUrl = window.URL.createObjectURL(blob);
      const tempLink = document.createElement('a');
      tempLink.href = blobUrl;
      tempLink.download = fileName;
      document.body.appendChild(tempLink);
      tempLink.click();
      document.body.removeChild(tempLink);
      window.URL.revokeObjectURL(blobUrl);
    } catch (error) {
      console.error('Error downloading file:', error);
    }
  }

  document.getElementById('fetchBtn').addEventListener('click', async () => {
    const embedLink = document.getElementById('embedLink').value.trim();
    const resultContainer = document.getElementById('resultContainer');
    resultContainer.innerHTML = 'Fetching CSS...';

    try {
      const response = await fetch(embedLink);
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      const cssText = await response.text();

      // Use a regex to extract each @font-face block
      const fontFaceRegex = /@font-face\s*{([^}]+)}/g;
      let match;
      const fonts = [];
      while ((match = fontFaceRegex.exec(cssText)) !== null) {
        const block = match[1];
        // Extract font-family
        const familyMatch = /font-family:\s*['"]?([^;'"]+)['"]?;/i.exec(block);
        const fontFamily = familyMatch ? familyMatch[1].trim() : 'unknown';
        // Extract font-style
        const styleMatch = /font-style:\s*([^;]+);/i.exec(block);
        const fontStyle = styleMatch ? styleMatch[1].trim() : 'normal';
        // Extract font-weight
        const weightMatch = /font-weight:\s*([^;]+);/i.exec(block);
        const fontWeight = weightMatch ? weightMatch[1].trim() : '400';
        // Extract src
        const srcMatch = /src:\s*([^;]+);/i.exec(block);
        if (!srcMatch) continue;
        let src = srcMatch[1].trim();

        // Extract URL from src using regex
        const urlRegex = /url\(([^)]+)\)/i;
        const urlMatch = urlRegex.exec(src);
        if (urlMatch) {
          let fontUrl = urlMatch[1].trim();
          // Remove quotes if present
          fontUrl = fontUrl.replace(/^['"]|['"]$/g, '');
          // We are keeping the original .woff2 URL
          fonts.push({
            family: fontFamily,
            style: fontStyle,
            weight: fontWeight,
            url: fontUrl
          });
        }
      }

      if (fonts.length === 0) {
        resultContainer.innerHTML = 'No fonts found in the provided CSS.';
        return;
      }

      // Display each font with a download link
      resultContainer.innerHTML = '';
      fonts.forEach(font => {
        const fontItem = document.createElement('div');
        fontItem.className = 'font-item';

        const info = document.createElement('span');
        info.textContent = `${font.family} - ${font.style} - ${font.weight}`;
        fontItem.appendChild(info);

        const link = document.createElement('span');
        link.textContent = 'Download .woff2';
        link.className = 'download-link';

        // Generate file name automatically (e.g., poppins-italic-300.woff2)
        const fileName = `${font.family.toLowerCase().replace(/\s+/g, '-')}` +
              `${font.style !== 'normal' ? '-' + font.style : ''}-${font.weight}.woff2`;

        // Add click listener to download the file with the proper name.
        link.addEventListener('click', (e) => {
          e.preventDefault();
          downloadFile(font.url, fileName);
        });

        fontItem.appendChild(link);
        resultContainer.appendChild(fontItem);
      });

    } catch (error) {
      resultContainer.innerHTML = 'Error fetching CSS: ' + error.message;
    }
  });
</script>


<style>
  .wrap p{
    line-height:2;
  }
  #resultContainer { 
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }
  .input-container { 
    margin-bottom: 20px;
  }
  input[type="text"] {
    width: 500px;
    padding: 10px;
    font-size: 14px;
    border: 1px solid #ccc;
    border-radius: 4px;
    margin-bottom: 10px;
  }
  #fetchBtn{
    padding: 20px;
font-size:14px;
color:white;
background:black
  }
  button:hover {
    background-color: #0056b3;
  }
  .font-item {
    background-color: #fff;
    border: 1px solid #ddd;
    padding: 10px;
    margin: 10px 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-radius: 4px;
    width: 360px;
  }
  .download-link {
    text-decoration: none;
    color: #007BFF;
    border: 1px solid #007BFF;
    padding: 5px 10px;
    border-radius: 4px;
    transition: background-color 0.3s;
    cursor: pointer;
  }
  .download-link:hover {
    background-color: #007BFF;
    color: #fff;
  }
</style>