

{"id":6496,"date":"2017-09-30T16:09:03","date_gmt":"2017-09-30T21:09:03","guid":{"rendered":"https:\/\/rud.is\/b\/?p=6496"},"modified":"2018-03-10T07:54:25","modified_gmt":"2018-03-10T12:54:25","slug":"identify-analyze-web-site-tech-stacks-with-rappalyzer","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/","title":{"rendered":"Identify &#038; Analyze Web Site Tech Stacks With rappalyzer"},"content":{"rendered":"<p>Modern websites are complex beasts. They house photo galleries, interactive visualizations, web fonts, analytics code and other diverse types of content. Despite the potential for diversity, many web sites share similar &#8220;tech stacks&#8221; &#8212; the components that come together to make them what they are. These stacks consist of web servers (often with special capabilities), cache managers and a wide array of front-end web components. Unless a site goes to great lengths to cloak what they are using, most of these stack components leave a fingerprint &#8212; bits and pieces that we can piece together to identify them.<\/p>\n<p><a href=\"https:\/\/wappalyzer.com\/\">Wappalyzer<\/a> is one tool that we can use to take these fingerprints and match them against a database of known components. If you&#8217;re not familiar with that service, go there now and enter in the URL of your own blog or company and come back to see why I&#8217;ve mentioned it.<\/p>\n<p>Back? Good.<\/p>\n<p>If you explored that site a bit, you likely saw a link to their <a href=\"https:\/\/github.com\/AliasIO\/Wappalyzer\">GitHub repo<\/a>. There you&#8217;ll find JavaScript source code and even some browser plugins along with the core &#8220;fingerprint database&#8221;, <a href=\"https:\/\/github.com\/AliasIO\/Wappalyzer\/blob\/master\/src\/apps.json\"><code>apps.json<\/code>?<\/a>. If you poke around on their repo, you&#8217;ll find the repo&#8217;s wiki and eventually see that folks have made various unofficial ports to <a href=\"https:\/\/github.com\/AliasIO\/Wappalyzer\">other languages<\/a>.<\/p>\n<p>By now, you&#8217;ve likely guessed that this blog post is introducing an R port of &#8220;wappalyzer&#8221; and if you have made such a guess, you&#8217;re correct! The <a href=\"https:\/\/github.com\/hrbrmstr\/rappalyzer\"><code>rappalyzer<\/code>?<\/a> package is a &#8220;work-in-progress&#8221; but it&#8217;s usable enough to get some feedback on the package API, solicit contributors and show some things you can do with it.<\/p>\n<h3>Just rappalyze something already!<\/h3>\n<p>For the moment, one real function is exposed: <code>rappalyze()<\/code>. Feed it a URL string or an <code>httr<\/code> <code>response<\/code> object and &#8212; if the analysis was fruitful &#8212; you&#8217;ll get back a data frame with all the identified tech stack components. Let&#8217;s see what <a href=\"http:\/\/jquery.com\/\"><code>jquery.com<\/code>?<\/a> is made of:<\/p>\n<pre id=\"rapple01\"><code class=\"language-r\">devtools::install_github(&quot;hrbrmstr\/rappalyzer&quot;)\r\n\r\nlibrary(rappalyzer)\r\n\r\nrappalyze(&quot;https:\/\/jquery.com\/&quot;)\r\n## # A tibble: 8 x 5\r\n##         tech              category match_type version confidence\r\n##        &lt;chr&gt;                 &lt;chr&gt;      &lt;chr&gt;   &lt;chr&gt;      &lt;dbl&gt;\r\n## 1 CloudFlare                   CDN    headers    &lt;NA&gt;        100\r\n## 2     Debian     Operating Systems    headers    &lt;NA&gt;        100\r\n## 3  Modernizr JavaScript Frameworks     script    &lt;NA&gt;        100\r\n## 4      Nginx           Web Servers    headers    &lt;NA&gt;        100\r\n## 5        PHP Programming Languages    headers  5.4.45        100\r\n## 6  WordPress                   CMS       meta   4.5.2        100\r\n## 7  WordPress                 Blogs       meta   4.5.2        100\r\n## 8     jQuery JavaScript Frameworks     script  1.11.3        100<\/code><\/pre>\n<p>If you played around on the Wappalyzer site you saw that it &#8220;spiders&#8221; many URLs to try to get a very complete picture of components that a given site may use. I just used the main jQuery site in the above example and we managed to get quite a bit of information from just that interaction.<\/p>\n<p>Wappalyzer (and, hence <code>rappalyzer<\/code>) works by comparing sets of regular expressions against different parts of a site&#8217;s content. For now, <code>rappalyzer<\/code> checks:<\/p>\n<ul>\n<li>the site URL (the one after a site&#8217;s been contacted &amp; content retrieved)<\/li>\n<li>HTTP headers (an invisible set of metadata browsers\/crawlers &amp; servers share)<\/li>\n<li>HTML content<\/li>\n<li>scripts<\/li>\n<li>meta tags<\/li>\n<\/ul>\n<p>Wappalyzer-proper runs in a browser-context, so it can pick up DOM elements and JavaScript environment variables which can provide some extra information not present in the static content.<\/p>\n<p>As you can see from the returned data frame, each tech component has one or more associated categories as well as a version number (if it could be guessed) and a value indicating how confident the guess was. It will also show where the guess came from (headers, scripts, etc).<\/p>\n<h3>A peek under the hood<\/h3>\n<p>I started making a pure R port of Wappalyzer but there are some frustrating &#8220;gotchas&#8221; with the JavaScript regular expressions that would have meant spending time identifying all the edge cases. Since the main Wappalyzer source is in JavaScript it was trivial to down-port it to a <a href=\"https:\/\/cran.r-project.org\/web\/packages\/V8\/index.html\"><code>V8<\/code>?<\/a>-compatible version and expose it via an R function. A longer-term plan is to deal with the regular expression conversion, but I kinda needed the functionality sooner than later (well, <em>wanted<\/em> it in R, anyway).<\/p>\n<p>On the other hand, keeping it in JavaScript has some advantages, especially with the advent of <a href=\"https:\/\/github.com\/deanmao\/node-chimera\"><code>chimera<\/code>?<\/a> (a phantomjs alternative that can put a full headless browser into a V8 engine context). Using that would mean getting the <code>V8<\/code> package ported to more modern version of the V8 source code which isn&#8217;t trivial, but doable. Using <code>chimera<\/code> would make it possible to identify even more tech stack components.<\/p>\n<p>Note also that these tech stack analyses can be dreadfully slow. That&#8217;s not due to using V8. The ones that slow are slow in all the language ports. This is due to the way the regular expressions are checked against the site content and for just using regular expressions to begin with. I&#8217;ve got some ideas to speed things up and may also introduce some &#8220;guide rails&#8221; to prevent lengthy operations and avoiding some checks if page characteristics meet certain criteria. Drop an issue if you have ideas as well.<\/p>\n<h3>Why is this useful?<\/h3>\n<p>Well, you can interactively see what a site uses like we did above. But, we can also look for commonalities across a number of sites. We&#8217;ll do this in a small example now. You can skip the expository and just <a href=\"https:\/\/github.com\/hrbrmstr\/rap1000\">work with the RStudio project<\/a> if that&#8217;s how you&#8217;d rather roll.<\/p>\n<h3>Crawling 1,000 orgs<\/h3>\n<p>I have a recent-ish copy of a list of Fortune 1000 companies and their industry sectors along with their website URLs. Let&#8217;s see how many of those sites we can still access and what we identify.<\/p>\n<p>I&#8217;m going to pause for <em>just a minute<\/em> to revisit some &#8220;rules&#8221; in the context of this operation.<\/p>\n<p>Specifically, I&#8217;m not:<\/p>\n<ul>\n<li>reading each site&#8217;s terms of service\/terms &amp; conditions<\/li>\n<li>checking each site&#8217;s <code>robots.txt<\/code> file<\/li>\n<li>using a uniquely identifying non-browser string crawler user-agent (since we need the site to present content like it would to a browser)<\/li>\n<\/ul>\n<p>However, I&#8217;m also not:<\/p>\n<ul>\n<li>using the site content in any way except to identify tech stack components (something dozens of organizations do)<\/li>\n<li>scraping past the index page HTML content, so there&#8217;s no measurable resource usage<\/li>\n<\/ul>\n<p>I <em>believe<\/em> I&#8217;ve threaded the ethical needle properly (and, I do this for a living), but if you&#8217;re uncomfortable with this you should use a different target URL list.<\/p>\n<p>Back to the code. We&#8217;ll need some packages:<\/p>\n<pre id=\"rapple02\"><code class=\"language-r\">library(hrbrthemes)\r\nlibrary(tidyverse)\r\nlibrary(curl)\r\nlibrary(httr)\r\nlibrary(rvest)\r\nlibrary(stringi)\r\nlibrary(urltools)\r\nlibrary(rappalyzer) # devtools::install_github(&quot;hrbrmstr\/rappalyzer&quot;)\r\nlibrary(rprojroot)\r\n# I&#039;m also using a user agent shortcut from the splashr package which is on CRAN<\/code><\/pre>\n<p>Now, I&#8217;ve included data in the RStudio project GH repo since it can be used later on to test out changes to <code>rappalyzer<\/code>. That&#8217;s the reason for the <code>if<\/code>\/<code>file.exists<\/code> tests. As I&#8217;ve said before, be kind to sites you scrape and cache content whenever possible to avoid consuming resources that you don&#8217;t own.<\/p>\n<p>Let&#8217;s take a look at our crawler code:<\/p>\n<pre id=\"rapple03\"><code class=\"language-r\">rt &lt;- find_rstudio_root_file()\r\n\r\nif (!file.exists(file.path(rt, &quot;data&quot;, &quot;f1k_gets.rds&quot;))) {\r\n\r\n  f1k &lt;- read_csv(file.path(rt, &quot;data&quot;, &quot;f1k.csv&quot;))\r\n\r\n  targets &lt;- pull(f1k, website)\r\n\r\n  results &lt;- list()\r\n  errors &lt;- list()\r\n\r\n  OK &lt;- function(res) {\r\n    cat(&quot;.&quot;, sep=&quot;&quot;)\r\n    results &lt;&lt;- c(results, list(res))\r\n  }\r\n\r\n  BAD &lt;- function(err_msg) {\r\n    cat(&quot;X&quot;, sep=&quot;&quot;)\r\n    errors &lt;&lt;- c(errors, list(err_msg))\r\n  }\r\n\r\n  pool &lt;- multi_set(total_con = 20)\r\n\r\n  walk(targets, ~{\r\n    multi_add(\r\n      new_handle(url = .x, useragent = splashr::ua_macos_chrome, followlocation = TRUE, timeout = 60),\r\n      OK, BAD\r\n    )\r\n  })\r\n\r\n  multi_run(pool = pool)\r\n\r\n  write_rds(results, file.path(rt, &quot;data&quot;, &quot;f1k_gets.rds&quot;), compress = &quot;xz&quot;)\r\n\r\n} else {\r\n  results &lt;- read_rds(file.path(rt, &quot;data&quot;, &quot;f1k_gets.rds&quot;))\r\n}<\/code><\/pre>\n<p>If you were expecting <code>read_html()<\/code> and\/or <code>GET()<\/code> calls you&#8217;re likely surprised at what you see. We&#8217;re trying to pull content from a thousand web sites, some of which may not be there anymore (for good or just temporarily). Sequential calls would need many minutes with error handling. We&#8217;re using the asynchronous\/parallel capabilities in the <a href=\"https:\/\/cran.r-project.org\/web\/packages\/curl\/index.html\"><code>curl<\/code>?<\/a> package to setup all 1,000 requests with the ability to capture the responses. There&#8217;s a hack-ish &#8220;progress&#8221; bar that uses <code>.<\/code> for &#8220;good&#8221; requests and <code>X<\/code> for ones that didn&#8217;t work. It still takes a little time (and you may need to tweak the <code>total_con<\/code> value on older systems) but way less than sequential <code>GET<\/code>s would have, and any errors are implicitly handled (ignored).<\/p>\n<p>The next block does the tech stack identification:<\/p>\n<pre id=\"rapple04\"><code class=\"language-r\">if (!file.exists(file.path(rt, &quot;data&quot;, &quot;rapp_results.rds&quot;))) {\r\n\r\n  results &lt;- keep(results, ~.x$status_code &lt; 300)\r\n  map(results, ~{\r\n    list(\r\n      url = .x$url,\r\n      status_code = .x$status_code,\r\n      content = .x$content,\r\n      headers = httr:::parse_headers(.x$headers)\r\n    ) -&gt; res\r\n    class(res) &lt;- &quot;response&quot;\r\n    res\r\n  }) -&gt; results\r\n\r\n  # this takes a *while*\r\n  pb &lt;- progress_estimated(length(results))\r\n  map_df(results, ~{\r\n    pb$tick()$print()\r\n    rap_df &lt;- rappalyze(.x)\r\n    if (nrow(rap_df) &gt; 0) rap_df &lt;- mutate(rap_df, url = .x$url)\r\n  }) -&gt; rapp_results\r\n\r\n  write_rds(rapp_results, file.path(rt, &quot;data&quot;, &quot;rapp_results.rds&quot;))\r\n\r\n} else {\r\n  rapp_results &lt;- read_rds(file.path(rt, &quot;data&quot;, &quot;rapp_results.rds&quot;))\r\n}<\/code><\/pre>\n<p>We filter out non-&#8220;OK&#8221; (HTTP 200-ish response) <code>curl<\/code> results and turn them into <em>just enough<\/em> of an <code>httr<\/code> <code>request<\/code> object to be able to work with them.<\/p>\n<p>Then we let <code>rappalyzer<\/code> work. I had time to kill so I let it run sequentially. In a production or time-critical context, I&#8217;d use the <a href=\"https:\/\/cran.r-project.org\/web\/packages\/future\/index.html\"><code>future<\/code>?<\/a> package.<\/p>\n<p>We&#8217;re <em>almost<\/em> down to data we can play with! Let&#8217;s join it back up with the original metadata:<\/p>\n<pre id=\"rapple05\"><code class=\"language-r\">left_join(\r\n  mutate(rapp_results, host = domain(rapp_results$url)) %&gt;%\r\n    bind_cols(suffix_extract(.$host))\r\n  ,\r\n  mutate(f1k, host = domain(website)) %&gt;%\r\n    bind_cols(suffix_extract(.$host)),\r\n  by = c(&quot;domain&quot;, &quot;suffix&quot;)\r\n) %&gt;%\r\n  filter(!is.na(name)) -&gt; rapp_results\r\n\r\nlength(unique(rapp_results$name))\r\n## [1] 754<\/code><\/pre>\n<p>Note that some orgs seem to have changed hands\/domains so we&#8217;re left with ~750 sites to play with (we could have tried to match more, but this is just an exercise). If you do the same <code>curl<\/code>-fetching exercise on your own, you may get fewer or more total sites. Internet crawling is fraught with peril and it&#8217;s not really possible to conveniently convey 100% production code in a blog post.<\/p>\n<h3>Comparing &#8220;Fortune 1000&#8221; org web stacks<\/h3>\n<p>Let&#8217;s see how many categories we picked up:<\/p>\n<pre id=\"rapple06\"><code class=\"language-r\">xdf &lt;- distinct(rapp_results, name, sector, category, tech)\r\n\r\nsort(unique(xdf$category))\r\n##  [1] &quot;Advertising Networks&quot;  &quot;Analytics&quot;             &quot;Blogs&quot;\r\n##  [4] &quot;Cache Tools&quot;           &quot;Captchas&quot;              &quot;CMS&quot;\r\n##  [7] &quot;Ecommerce&quot;             &quot;Editors&quot;               &quot;Font Scripts&quot;\r\n## [10] &quot;JavaScript Frameworks&quot; &quot;JavaScript Graphics&quot;   &quot;Maps&quot;\r\n## [13] &quot;Marketing Automation&quot;  &quot;Miscellaneous&quot;         &quot;Mobile Frameworks&quot;\r\n## [16] &quot;Programming Languages&quot; &quot;Tag Managers&quot;          &quot;Video Players&quot;\r\n## [19] &quot;Web Frameworks&quot;        &quot;Widgets&quot;<\/code><\/pre>\n<p>Plenty to play with!<\/p>\n<p>Now, what do you think the most common tech component is across all these diverse sites?<\/p>\n<pre id=\"rapple07\"><code class=\"language-r\">count(xdf, tech, sort=TRUE)\r\n## # A tibble: 115 x 2\r\n##                        tech     n\r\n##                       &lt;chr&gt; &lt;int&gt;\r\n##  1                   jQuery   572\r\n##  2       Google Tag Manager   220\r\n##  3                Modernizr   197\r\n##  4        Microsoft ASP.NET   193\r\n##  5          Google Font API   175\r\n##  6        Twitter Bootstrap   162\r\n##  7                WordPress   150\r\n##  8                jQuery UI   143\r\n##  9             Font Awesome   118\r\n## 10 Adobe Experience Manager    69\r\n## # ... with 105 more rows<\/code><\/pre>\n<p>I had suspected it was <code>jQuery<\/code> (and hinted at that when I used it as the initial <code>rappalyzer<\/code> example). In a future blog post we&#8217;ll look at just how vulnerable orgs are based on which CDNs they use (many use similar jQuery and other resource CDNs, and use them insecurely).<\/p>\n<p>Let&#8217;s see how broadly each tech stack category is used across the sectors:<\/p>\n<pre id=\"rapple08\"><code class=\"language-r\">group_by(xdf, sector) %&gt;%\r\n  count(category) %&gt;%\r\n  ungroup() %&gt;%\r\n  arrange(category) %&gt;%\r\n  mutate(category = factor(category, levels=rev(unique(category)))) %&gt;%\r\n  ggplot(aes(category, n)) +\r\n  geom_boxplot() +\r\n  scale_y_comma() +\r\n  coord_flip() +\r\n  labs(x=NULL, y=&quot;Tech\/Services Detected across Sectors&quot;,\r\n       title=&quot;Usage of Tech Stack Categories by Sector&quot;) +\r\n  theme_ipsum_rc(grid=&quot;X&quot;)<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/plot_zoom_png.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"6504\" data-permalink=\"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/plot_zoom_png-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/plot_zoom_png.png?fit=1900%2C1220&amp;ssl=1\" data-orig-size=\"1900,1220\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"plot_zoom_png\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/plot_zoom_png.png?fit=510%2C327&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/plot_zoom_png.png?resize=510%2C327&#038;ssl=1\" alt=\"\" width=\"510\" height=\"327\" class=\"aligncenter size-full wp-image-6504\" \/><\/a><\/p>\n<p>That&#8217;s <em>alot<\/em> of JavaScript. But, there&#8217;s also large-ish use of CMS, Web Frameworks and other components.<\/p>\n<p>I wonder what the CMS usage looks like:<\/p>\n<pre id=\"rapple09\"><code class=\"language-r\">filter(xdf, category==&quot;CMS&quot;) %&gt;%\r\n  count(tech, sort=TRUE)\r\n## # A tibble: 15 x 2\r\n##                        tech     n\r\n##                       &lt;chr&gt; &lt;int&gt;\r\n##  1                WordPress    75\r\n##  2 Adobe Experience Manager    69\r\n##  3                   Drupal    68\r\n##  4               Sitefinity    26\r\n##  5     Microsoft SharePoint    19\r\n##  6                 Sitecore    14\r\n##  7                      DNN    11\r\n##  8                Concrete5     6\r\n##  9     IBM WebSphere Portal     4\r\n## 10        Business Catalyst     2\r\n## 11                    Hippo     2\r\n## 12                TYPO3 CMS     2\r\n## 13               Contentful     1\r\n## 14              Orchard CMS     1\r\n## 15             SilverStripe     1<\/code><\/pre>\n<p>Drupal and WordPress weren&#8217;t shocking to me (again, I do this for a living) but they may be to others when you consider this is the Fortune 1000 we&#8217;re talking about.<\/p>\n<p>What about Web Frameworks?<\/p>\n<pre id=\"rapple10\"><code class=\"language-r\">filter(xdf, category==&quot;Web Frameworks&quot;) %&gt;%\r\n  count(tech, sort=TRUE)\r\n## # A tibble: 7 x 2\r\n##                          tech     n\r\n##                         &lt;chr&gt; &lt;int&gt;\r\n## 1           Microsoft ASP.NET   193\r\n## 2           Twitter Bootstrap   162\r\n## 3             ZURB Foundation    61\r\n## 4               Ruby on Rails     2\r\n## 5            Adobe ColdFusion     1\r\n## 6                    Kendo UI     1\r\n## 7 Woltlab Community Framework     1<\/code><\/pre>\n<p>Yikes! Quite a bit of ASP.NET. But, many enterprises haven&#8217;t migrated to more modern, useful platforms (yet).<\/p>\n<h3>FIN<\/h3>\n<p>As noted earlier, the data &amp; code are <a href=\"https:\/\/github.com\/hrbrmstr\/rap1000\">on GitHub<\/a>. There are many questions you can ask and answer with this data set and definitely make sure to share any findings you discover!<\/p>\n<p>We&#8217;ll continue exploring different aspects of what you can glean from looking at web sites in a different way in future posts.<\/p>\n<p>I&#8217;ll leave you with one interactive visualization that lets you explore the tech stacks by sector.<\/p>\n<pre id=\"rapple11\"><code class=\"language-r\">devtools::install_github(&quot;jeromefroe\/circlepackeR&quot;)\r\nlibrary(circlepackeR)\r\nlibrary(data.tree)\r\nlibrary(treemap)\r\n\r\ncpdf &lt;- count(xdf, sector, tech)\r\n\r\ncpdf$pathString &lt;- paste(&quot;rapp&quot;, cpdf$sector, cpdf$tech, sep = &quot;\/&quot;)\r\nstacks &lt;- as.Node(cpdf)\r\n\r\ncirclepackeR(stacks, size = &quot;n&quot;, color_min = &quot;hsl(56,80%,80%)&quot;,\r\n             color_max = &quot;hsl(341,30%,40%)&quot;, width = &quot;100%&quot;, height=&quot;800px&quot;)<\/code><\/pre>\n<p><center><\/p>\n<p><iframe style=\"width:100%;height=750px\" seamless src=\"https:\/\/rud.is\/rpubs\/rapstack\/index.html\"><\/iframe><\/p>\n<p><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern websites are complex beasts. They house photo galleries, interactive visualizations, web fonts, analytics code and other diverse types of content. Despite the potential for diversity, many web sites share similar &#8220;tech stacks&#8221; &#8212; the components that come together to make them what they are. These stacks consist of web servers (often with special capabilities), [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6517,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[91,725],"tags":[810],"class_list":["post-6496","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-r","category-web-scraping","tag-post"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Identify &amp; Analyze Web Site Tech Stacks With rappalyzer - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Identify &amp; Analyze Web Site Tech Stacks With rappalyzer - rud.is\" \/>\n<meta property=\"og:description\" content=\"Modern websites are complex beasts. They house photo galleries, interactive visualizations, web fonts, analytics code and other diverse types of content. Despite the potential for diversity, many web sites share similar &#8220;tech stacks&#8221; &#8212; the components that come together to make them what they are. These stacks consist of web servers (often with special capabilities), [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2017-09-30T21:09:03+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-03-10T12:54:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1588\" \/>\n\t<meta property=\"og:image:height\" content=\"1590\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Identify &#038; Analyze Web Site Tech Stacks With rappalyzer\",\"datePublished\":\"2017-09-30T21:09:03+00:00\",\"dateModified\":\"2018-03-10T12:54:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/\"},\"wordCount\":1632,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1\",\"keywords\":[\"post\"],\"articleSection\":[\"R\",\"web scraping\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/\",\"name\":\"Identify & Analyze Web Site Tech Stacks With rappalyzer - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1\",\"datePublished\":\"2017-09-30T21:09:03+00:00\",\"dateModified\":\"2018-03-10T12:54:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1\",\"width\":1588,\"height\":1590},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/09\\\/30\\\/identify-analyze-web-site-tech-stacks-with-rappalyzer\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Identify &#038; Analyze Web Site Tech Stacks With rappalyzer\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rud.is\\\/b\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\\\/\\\/rud.is\"],\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/author\\\/hrbrmstr\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Identify & Analyze Web Site Tech Stacks With rappalyzer - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/","og_locale":"en_US","og_type":"article","og_title":"Identify & Analyze Web Site Tech Stacks With rappalyzer - rud.is","og_description":"Modern websites are complex beasts. They house photo galleries, interactive visualizations, web fonts, analytics code and other diverse types of content. Despite the potential for diversity, many web sites share similar &#8220;tech stacks&#8221; &#8212; the components that come together to make them what they are. These stacks consist of web servers (often with special capabilities), [&hellip;]","og_url":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/","og_site_name":"rud.is","article_published_time":"2017-09-30T21:09:03+00:00","article_modified_time":"2018-03-10T12:54:25+00:00","og_image":[{"width":1588,"height":1590,"url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","type":"image\/png"}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Identify &#038; Analyze Web Site Tech Stacks With rappalyzer","datePublished":"2017-09-30T21:09:03+00:00","dateModified":"2018-03-10T12:54:25+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/"},"wordCount":1632,"commentCount":4,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","keywords":["post"],"articleSection":["R","web scraping"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/","url":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/","name":"Identify & Analyze Web Site Tech Stacks With rappalyzer - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","datePublished":"2017-09-30T21:09:03+00:00","dateModified":"2018-03-10T12:54:25+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","width":1588,"height":1590},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2017\/09\/30\/identify-analyze-web-site-tech-stacks-with-rappalyzer\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Identify &#038; Analyze Web Site Tech Stacks With rappalyzer"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/09\/Viewer_Zoom.png?fit=1588%2C1590&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p23idr-1GM","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":727,"url":"https:\/\/rud.is\/b\/2011\/12\/30\/three-resolutions-for-web-developers\/","url_meta":{"origin":6496,"position":0},"title":"Three Resolutions For Web Developers","author":"hrbrmstr","date":"2011-12-30","format":false,"excerpt":"I'm on a \"three things\" motif for 2012, as it's really difficult for most folks to focus on more than three core elements well. This is especially true for web developers as they have so much to contend with on a daily basis, whether it be new features, bug reports,\u2026","rel":"","context":"In &quot;Breach&quot;","block_context":{"text":"Breach","link":"https:\/\/rud.is\/b\/category\/breach\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13860,"url":"https:\/\/rud.is\/b\/2023\/03\/25\/linking-lits-lightweight-web-components-and-webr-for-vanilla-js-reactivity\/","url_meta":{"origin":6496,"position":1},"title":"Linking Lit&#8217;s Lightweight Web Components And WebR For Vanilla JS Reactivity","author":"hrbrmstr","date":"2023-03-25","format":false,"excerpt":"See it live before reading! This is a Lit + WebR reproduction of the OG Shiny Demo App Lit is a javascript library that makes it a bit easier to work with Web Components, and is especially well-suited in reactive environments. My recent hack-y WebR experiments have been using Reef\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"some descriptive text you can read at the linked url in the post. there's also a popup menu and a barplot.","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/lit-webr-phones.png?fit=1200%2C972&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/lit-webr-phones.png?fit=1200%2C972&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/lit-webr-phones.png?fit=1200%2C972&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/lit-webr-phones.png?fit=1200%2C972&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/lit-webr-phones.png?fit=1200%2C972&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":12083,"url":"https:\/\/rud.is\/b\/2019\/03\/14\/collecting-content-security-policy-violation-reports-in-s3-effortlessly-freely\/","url_meta":{"origin":6496,"position":2},"title":"Collecting Content Security Policy Violation Reports in S3 (&#8216;Effortlessly&#8217;\/&#8217;Freely&#8217;)","author":"hrbrmstr","date":"2019-03-14","format":false,"excerpt":"In the previous post I tried to explain what Content Security Policies (CSPs) are and how to work with them in R. In case you didn't RTFPost the TLDR is that CSPs give you control over what can be loaded along with your web content and can optionally be configured\u2026","rel":"","context":"In &quot;Cybersecurity&quot;","block_context":{"text":"Cybersecurity","link":"https:\/\/rud.is\/b\/category\/cybersecurity\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13885,"url":"https:\/\/rud.is\/b\/2023\/03\/26\/%f0%9f%a7%aa-lit-webr-observable-plot-linking-lits-lightweight-web-components-and-webr-for-vanilla-js-reactivity-js-datavis\/","url_meta":{"origin":6496,"position":3},"title":"? Lit + WebR + Observable Plot: Linking Lit&#8217;s Lightweight Web Components And WebR For Vanilla JS Reactivity &#038; JS DataVis","author":"hrbrmstr","date":"2023-03-26","format":false,"excerpt":"See it live before reading! The previous post brought lit-webr, to introduce Lit and basic reactivity. Today, is more of the same, but we bring the OG Shiny demo plot into the modern age by using Observbable Plot to make the charts. We're still pulling data from R, but we're\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"popup menu + barplot","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/preview.png?fit=1200%2C1174&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/preview.png?fit=1200%2C1174&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/preview.png?fit=1200%2C1174&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/preview.png?fit=1200%2C1174&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/03\/preview.png?fit=1200%2C1174&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":1705,"url":"https:\/\/rud.is\/b\/2012\/10\/22\/putting-cybercrime-infographics-behind-bars\/","url_meta":{"origin":6496,"position":4},"title":"Putting Cybercrime [Infographics] Behind Bars","author":"metricshulk","date":"2012-10-22","format":false,"excerpt":"HP & the Ponemon Institute have released their third annual \"Cost of Cybercrime\" report and the web wizards at HP have given us an infographic from it: (You can see the full size one at the above link) While some designers may think that infographic visualizations are not subject to\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13963,"url":"https:\/\/rud.is\/b\/2023\/04\/16\/start-creating-vanilla-js-webr-apps-with-less-inertia\/","url_meta":{"origin":6496,"position":5},"title":"Start Creating Vanilla JS WebR Apps With Less Inertia","author":"hrbrmstr","date":"2023-04-16","format":false,"excerpt":"WebR has a template for React, but I'm not a fan of it or Vue (a fact longtime readers are likely tired of hearing right about now). It's my opinion and experience that Lit webcomponents come closer to \u201cbare metal\u201d webcomponents, which means the \u201clock-in\u201d with Lit is way less\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"dark mode webr web app","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/04\/dark.png?fit=1200%2C754&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/04\/dark.png?fit=1200%2C754&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/04\/dark.png?fit=1200%2C754&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/04\/dark.png?fit=1200%2C754&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/04\/dark.png?fit=1200%2C754&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/6496","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=6496"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/6496\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media\/6517"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=6496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=6496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=6496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}