How to download multiple formats of a web font from the (official) Google Web Fonts repo? - webfonts

I've learnt that Google automatically serves TTF, EOT, WOFF, or SVG font files depending on the browser / device it's accessed from.
Now I am planning to host and serve the font files from my server itself, for which I would first have to download all the file formats of the web font(s).
How or where can I download the 4 file formats for a web font that I would like to use?
PS: By using different browsers -- Chrome, IE9 and Safari (dev - iPhone UA), I was able to get the WOFF, EOT and TTF formats. No luck with the SVG format though. It would be awesome if there's an even simpler way.
EDIT: Oh, and by the way, I do know that I can download various formats from fontsquirrel, but I am talking about downloading from the official repo here.

======= UPDATED 2016-05-31 =======
I made a tiny PHP script to get download links from a Google Fonts CSS import URL like: https://fonts.googleapis.com/css?family=Roboto:400,700|Slabo+27px|Lato:400,300italic,900italic
You can use this tool here: http://nikoskip.me/gfonts.php
For instance, if you use the above import URL, you will get this:
I got tired about updating this answer on each new release of Chrome, because they always change the way you can spoof the User Agent string, so please use this script instead.
======= OLD SOLUTION =======
Using DevTools from Chrome you can override the User Agent.
How to:
Get the font that you need at Google Fonts page.
You will get an URL to import in your CSS, like: http://fonts.googleapis.com/css?family=Cabin:500,700,500italic,700italic
Open that URL in your browser and you will see the full URL where you can actually download the font.
Go to Developer Tools (F12) and press ESC
Select "Emulation" tab and then click on "Network" sub-tab
Finally on Spoof user agent select IE9 for EOT format, Android 4 for TTF and this UA String for SVG: Mozilla/4.0 (iPad; CPU OS 4_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/4.1 Mobile/9A405 Safari/7534.48.3 (thanks anonymous)

You can clone the Google webfonts directory at http://code.google.com/p/googlefontdirectory/
You can also get single font files at http://code.google.com/p/googlefontdirectory/source/browse/#font_name

How to get the font download urls, including SVG and woff2.
The user-agents required to download each font are as follows. source.
module.exports = {
USER_AGENTS: {
eot: 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)',
woff: 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0',
woff2: 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/38.0.2125.104 Safari/537.36', // complete woff2 file for one variant
svg: 'Mozilla/4.0 (iPad; CPU OS 4_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/4.1 Mobile/9A405 Safari/7534.48.3',
ttf: 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16'
},
GOOGLE_FONTS_API_KEY: 'AIzaSyDY-C-Lt9uyPP5fSTjMCR4bB944SlI4spw',
CACHE_DIR: __dirname + "/cachedFonts/",
}
Add these useragents using devtool.
source
you can now visit https://fonts.googleapis.com/css?family=Open+Sans and spoof your user agent, download the fonts by visiting the url found in the #font-face.
Alternatively google-webfonts-helper does it all for you.
There's a great blog post here from the developer where I acquired the image.
Why do you want to self host?
Always use a common CDN if possible, its a lot more likely that your font won't even need downloading(browser cached).
If you are worried about google sending the wrong font to users, most likely because they are spoofing their user-agent, Then there in another option and still get the benefits of using google hosting.
Insert the #font-face yourself, just use the steps above to find the google font url and insert this into the <head>;
<style>
#font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: url(google-font-url-here/opensans.eot);
src: local('Open Sans'), local('OpenSans'),
url(google-font-url-here/opensans.eot?#iefix) format('embedded-opentype'),
url(google-font-url-here/opensans.woff2) format('woff2'),
url(google-font-url-here/opensans.woff) format('woff'),
url(google-font-url-here/opensans.ttf) format('truetype'),
url(google-font-url-here/opensans.svg#OpenSans) format('svg');
}
</style>
This comes with its risks as the URLS may change!

https://github.com/google/fonts
old answer:
I made online clone of https://code.google.com/archive/p/googlefontdirectory/ :)
https://bitbucket.org/Tymek/google-web-fonts/ There you go!

I wrote a PowerShell script to automatically download the fonts served to several different User Agents. For the basic font, it gets all four formats (woff, ttf, svg, eot). Google doesn't seem to serve SVG and EOT files for the bold and italic weights.
$agents = "Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0",`
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1",`
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)",`
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",`
"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)"
foreach($arg in $args) {
$arg;
foreach($agent in $agents) {
$agent;
$webclient = New-Object System.Net.WebClient
[void]$webclient.Headers.Add("user-agent", $agent)
$url = "http://fonts.googleapis.com/css?family=$arg"
$css = $webclient.DownloadString($url)
$css
$fonts = $css |
Select-String -AllMatches "http://[A-Za-z0-9/._?&=%-]+" |
Select-Object -ExpandProperty Matches |
Select-Object -ExpandProperty Value
foreach($font in $fonts) {
$font
$fontfile = [System.Io.Path]::GetFileName((new-object System.Uri $font).LocalPath)
[void]$webclient.DownloadFile($font, "$pwd\$fontfile")
}
}
}
Once it's in a .ps1 file, it can be called with the fonts to download as arguments:
PS> .\DownloadFonts.ps1 "Open+Sans:400,700,400italic,700italic"
The script will output the CSS pulled from Google's servers to help you figure out which file is which (e.g. in my case the SVG font was pulled as a file called "font").
This is based on bash scripts posted by RichardN and ldeck on the blog post Locally Caching Google Web Fonts.
For reference, here is ldeck's bash script:
#!/bin/sh
for family in $*; do
for url in $( {
for agent in \
'Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0' \
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1' \
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)' ;
do
curl -A "$agent" -s "http://fonts.googleapis.com/css?family=$family" | \
grep -oE 'http://[A-Za-z0-9/._-]+'; \
done } | sort -u ) ;
do
extn=${url##*.} ;
file=$(echo "$family"| tr +[:upper:] _[:lower:]);
echo $url $file.$extn;
curl -s "$url" -o "$file.$extn";
done
done
Further reference: Using HTML5 AppCache.

I've wrote a python script as part of my work on the open-source project MDIDX. it will get all possible font formats of a given font-family from Google Fonts CDN. It's naive - brute-forcing common platforms' user-agents
It can be simplified like so:
import re
import os
import requests
def main():
font_family = "Material Icons"
output_directory = "fonts"
download_fonts(font_family, output_directory)
def download_fonts(font_family, output_directory, output_file_name=None):
if not os.path.isdir(output_directory):
os.makedirs(output_directory)
if not output_file_name:
output_file_name = font_family.lower().replace(" ","-")
user_agents = USER_AGENTS.splitlines()
user_agents = map(lambda x: x, user_agents)
font_urls = set()
for user_agent in user_agents:
url = 'https://fonts.googleapis.com/icon?family={}'.format("+".join(font_family.strip().split()))
r = requests.get(url, headers={"user-agent": user_agent})
r.raise_for_status()
urls = re.findall('url\((.*?)\)', r.text)
urls = map(str, urls)
urls = filter(str, urls)
font_urls.update(urls)
fonts_map = {font_url.split('.')[-1].lower(): font_url for font_url in font_urls}
for file_extension, url in fonts_map.items():
file_path = os.path.join(output_directory, '{output_file_name}.{file_extension}'.format(output_file_name=output_file_name, file_extension=file_extension))
_download_file(url, file_path)
USER_AGENTS = """
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3
Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.6 Safari/532.1
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.2)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Win64; x64; Trident/4.0)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; .NET CLR 2.0.50727; InfoPath.2)Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)
Mozilla/4.0 (compatible; MSIE 6.1; Windows XP)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; da-dk) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00
Mozilla/5.0 (Linux; U; Android 2.3.4; fr-fr; HTC Desire Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-N920C Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/6.2 Chrome/56.0.2924.87 Mobile Safari/537.36
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 BIDUBrowser/2.x Safari/537.31
Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; GT-I9500 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.0 QQ-URL-Manager Mobile Safari/537.36
Mozilla/5.0 (Android 8.0.0; Tablet; rv:57.0) Gecko/57.0 Firefox/57.0
Mozilla/5.0 (Android 8.1.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0
"""
def _download_file(url, file_path):
r = requests.get(url)
r.raise_for_status()
with open(file_path, 'wb') as f:
f.write(r.content)
if __name__ == '__main__':
main()

Related

What can cause chrome to send user-agent with random suffix?

I have a user with the following user-agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36/Z7F3WKeKMrnlzpp
This suffix Z7F3WKeKMrnlzpp is different (seemingly random) for every request. The only unusual extension that he has is "360 internet protection", but this is not supposed to cause such behavior.
Thanks

Different server output in Firefox vs Chrome, why?

Running IIS 10 on Server 2019, fully patched. I have the following .aspx webpage code:
For Each var As String In Request.ServerVariables
Response.Write(var &" "& Request(var))
Next
Why does Firefox purposefully (apparently) ignore the HTTP_SEC_FETCH_ server headers while Chrome happily displays them?
Firefox 69.0.1 output:
...
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
HTTP_UPGRADE_INSECURE_REQUESTS 1
Chrome 77.0.3865.90 output:
...
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
HTTP_UPGRADE_INSECURE_REQUESTS 1
HTTP_SEC_FETCH_MODE navigate
HTTP_SEC_FETCH_USER ?1
HTTP_SEC_FETCH_SITE none
This is server output so why does Firefox ignore that data? Or am I not understanding how server variables work? The output above is at the very end of the list.
It turns out that Chrome is (once again) ahead of Firefox in following RFC and various miscellaneous stuff. In this case it is a thing called "Fetch Metadata Request Headers" per https://www.w3.org/TR/fetch-metadata/ and is inserted into the fetch request by the browser. Now I know. (And knowing is half the battle!)

How to tell web server that some HTTP client (which is not known officially) supports HTML5?

How to tell web server that some HTTP client (which is not known officially) supports HTML5? As I know, HTTP servers check what browser and version. But if I want to send HTTP request with header "User-Agent: SomeUnknownAgent" - how I must notify remote HTTP server that this "SomeUnknownAgent" supports HTML5? Here are sample "User-Agent" values:
Chrome 6.0.472.63: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3
Firefox 3.6.10: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10
Firefox 4.0 Beta 6: Mozilla/5.0 (Windows NT 5.1; rv:2.0b6) Gecko/20100101 Firefox/4.0b6
Internet Explorer 8.0.6001.18702: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Opera 10.63: Opera/9.80 (Windows NT 5.1; U; en) Presto/2.6.30 Version/10.63
Safari 5.0.2: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
I found these in common: Windows; U; Windows NT 5.1;. Maybe it is enough to include?
I found an answer. It helped a lot to read here. So the answer for example could be:
"User-Agent: SomeUnknownAgent 1.0.0.0: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Gecko/20100101"
Now HTTP server knows that browser supports HTML5. Of course, if it's rely on "User-Agent" field.

Detect Google Chrome Aura with JavaScript, possible?

navigator.userAgent
does not report it:
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1613.1 Safari/537.36"
I only see it (Aura) literally in chrome://version/strings.js, which gets reported in chrome://version/

What is causing these /cache/xxx entries in our logs?

We have a valid url with the path '/some/url', but we are experiencing errors in our logs caused by the fact that something is attempting to access: '/some/url/cache/526402928a7041a5c61ae7da95c679c3' (an invalid url).
The '/some/url' part varies but the client rather consistently tries to get './cache/xxx'.
Does anyone know why the client is attempting to retrieve this url - which component/plugin is causing this?
The user agent is:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11
or
Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11
Found the cause at:
http://code.google.com/p/chromium/issues/detail?id=132059
Likely caused by a malfunctioning extension: "Browser Companion Helper" part of "Ginyas Browser Companion