Skip to content

Instantly share code, notes, and snippets.

@nikoskip
Last active September 20, 2022 21:34
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save nikoskip/bcf58106f728a3e7b7f9dcb6edaa1e82 to your computer and use it in GitHub Desktop.
Save nikoskip/bcf58106f728a3e7b7f9dcb6edaa1e82 to your computer and use it in GitHub Desktop.
Demo: http://nikoskip.me/gfonts.php | You only have to use the CSS import URL that Google gives you, for instance: http://fonts.googleapis.com/css?family=Cabin:500,700,500italic,700italic
<?php
$fontTypes = array('woff2', 'woff', 'ttf', 'svg', 'eot');
$gFontURL = 'http://fonts.googleapis.com/css?family=';
$uaFonts = array(
'woff2' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36',
'woff' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/4.0; GTB7.4; InfoPath.3; SV1; .NET CLR 3.1.76908; WOW64; en-US)',
'ttf' => 'Mozilla/5.0 (Linux; U; Android 2.2.1; en-ca; LG-P505R Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'svg' => 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10',
'eot' => 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)'
);
function curlGoogleFont($url, $ua) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => $ua
));
if (($response = curl_exec($curl))) {
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
if (strrpos($header, 'Content-Type: text/css')) {
return $response;
}
}
return '';
}
function parseCss($css) {
$fonts = array();
$fontName = null;
$fontStyle = null;
$fontWeight = null;
$url = null;
foreach (preg_split('/\r\n|\n|\r/', $css) as $cssLine) {
// We save the font-family name for EOT
if (strpos($cssLine, 'font-family')) {
preg_match("/'(.*?)'/i", $cssLine, $data);
$fontName = $data[1];
}
if (strpos($cssLine, 'url')) {
preg_match('/local\((.*?)\)/i', $cssLine, $data);
if (count($data)) {
$fontName = str_replace('\'', '', $data[1]);
}
}
if (strpos($cssLine, 'src')) {
preg_match('/url\((.*?)\)/i', $cssLine, $data);
$url = $data[1];
}
if (strpos($cssLine, 'font-style')) {
preg_match("/\: '?(.*?)'?;$/i", $cssLine, $data);
$fontStyle = $data[1];
}
if (strpos($cssLine, 'font-weight')) {
preg_match("/\: '?(.*?)'?;$/i", $cssLine, $data);
$fontWeight = $data[1];
}
if ($fontName !== null && $url !== null) {
$fonts[implode('-', array($fontName, $fontStyle, $fontWeight))] = $url;
$fontStyle = null;
$fontWeight = null;
$fontName = null;
$url = null;
}
}
return $fonts;
}
if (isset($_POST['url'])) {
$urlParts = parse_url($_POST['url']);
parse_str($urlParts['query'], $queryParts);
$gFontURL .= urlencode($queryParts['family']);
$fontsDownloadLinks = array();
foreach ($fontTypes as $fontType) {
$content = curlGoogleFont($gFontURL, $uaFonts[$fontType]);
$fontsDownloadLinks[$fontType] = parseCss($content);
}
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Download Google Fonts - Simple PHP Script</title>
</head>
<body>
<p>Thanks for visiting. Please provide your Google Fonts URL to import in your CSS (example: http://fonts.googleapis.com/css?family=Cabin:500,700,500italic,700italic) and you will get links for download <?php echo implode(', ', $fontTypes); ?> fonts.</p>
<form action="" method="post">
Google Fonts URL: <input type="text" name="url" value="<?php if(isset($_POST['url'])) echo $_POST['url']; ?>">
<input type="submit" value="Get fonts!">
</form>
<?php if (isset($fontsDownloadLinks)) { ?>
<hr>
<?php foreach ($fontsDownloadLinks as $font => $links) { ?>
<strong><?php echo $font; ?></strong>
<?php echo count($links) === 0 ? '<p>Not found</p>' : ''; ?>
<table border="1" cellspacing="0" cellpadding="2">
<tr>
<?php foreach ($links as $fontName => $link) { ?>
<td><a href="<?php echo $link; ?>"><?php echo $fontName; ?></a></td>
<?php } ?>
</table>
<?php
}
}
?>
<hr>
<a href="https://twitter.com/nikoskip">Contact</a> | <a href="https://gist.github.com/nikoskip/bcf58106f728a3e7b7f9dcb6edaa1e82">Download code</a>
</body>
</html>
@boycce
Copy link

boycce commented Oct 19, 2016

Thanks!

@nedzen
Copy link

nedzen commented Nov 28, 2016

Many thanks ! you're my hero !

@slayer49
Copy link

+1, save me time of writing my own switching user agents in browser

@nikoskip
Copy link
Author

I have updated the script. A bug reported from StackOverflow where some ttf fonts were not being fetched.

@jnaklaas
Copy link

jnaklaas commented Feb 11, 2017

Is it normal that for eot and svg it only creates a download link for font-weight 400, even if the google font link contains more?

link example: https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700

While I'm at it: the user agent for woff2 generates a link for each subset (latin, cyrillic, whatnot, ...). Right now it just overwrites each link until it reaches the last subset, which is the latin subset. So you should be aware that, while for ttf and woff the whole fonts are downloaded, for woff2 only latin characters are included.

I've searched for a user-agent that downloads the woff2 file with all subsets included but haven't found one.

@nikoskip
Copy link
Author

nikoskip commented Feb 24, 2017

@jnaklaas I just realized about that. For sure Google is saving bytes doing it that way: downloading only what you need. I'm going to investigate a way to get the full woff2 file, and if I can't maybe I will modify the script to list each subset respectively.

Copy link

ghost commented Jul 25, 2017

@nikoskip that's an awesome solution,
-btw.
for the missing eot, I've checked if the variation actually exist in here,
if it was (you can see ttf with "bold" suffix for example), I've downloaded it and used this to convert the ttf to eot...
since I'm doing this one-time, it's cool..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment