Orchestrates the complete PageRank calculation workflow, including URL cleaning, redirect resolution, edge deduplication, indexability handling, nofollow handling, isolate handling, and PageRank computation.
Usage
pagerank(
edge_list_df,
redirects_df = NULL,
clean_edge_urls = TRUE,
clean_redirect_urls = TRUE,
rurl_params = list(),
self_loops = c("drop", "keep"),
drop_isolates_flag = TRUE,
reverse = FALSE,
weight_col = NULL,
duplicate_edge_policy = c("collapse", "aggregate", "count_instances"),
nofollow_col = NULL,
nofollow_action = c("evaporate", "drop", "keep"),
indexability_df = NULL,
indexability_url_col = "url",
indexability_status_col = "indexability_status",
robots_blocked_action = c("trap", "vanish"),
edge_from_col = "from",
edge_to_col = "to",
redirect_from_col = "from",
redirect_to_col = "to",
duplicate_from_policy = c("strict", "first_wins", "last_wins", "most_frequent",
"prune_source", "resolve_if_consistent"),
loop_handling = c("error", "prune_loop", "break_arrow"),
canonicals_df = NULL,
canonical_from_col = "from",
canonical_to_col = "to",
clean_canonical_urls = TRUE,
canonical_duplicate_from_policy = c("strict", "first_wins", "last_wins",
"most_frequent", "prune_source", "resolve_if_consistent"),
canonical_loop_handling = c("error", "prune_loop", "break_arrow"),
canonical_conflict_policy = c("redirect_wins", "error", "canonical_wins"),
out_of_scope_fold = c("relabel", "keep", "leak"),
keep_domains = NULL,
exclude_domains = NULL,
keep_hosts = NULL,
exclude_hosts = NULL,
prior_df = NULL,
prior_url_col = "url",
prior_weight_col = "weight",
prior_transform = c("none", "log", "percentile", "minmax", "zipf", "rank_linear"),
prior_alpha = 0,
prior_inject_unmatched = FALSE,
prior_verbose = TRUE,
damping = 0.85,
...
)Arguments
- edge_list_df
A data frame representing the edge list, typically with columns like "from" and "to".
- redirects_df
An optional data frame for redirect rules, typically with "from" and "to" columns. Defaults to NULL.
- clean_edge_urls
Logical, whether to clean URLs in the edge list. Defaults to TRUE.
- clean_redirect_urls
Logical, whether to clean URLs in the redirect list. Defaults to TRUE. Only effective if `redirects_df` is provided.
- rurl_params
A list of parameters to pass to `rurl::clean_url`. Defaults to an empty list. `protocol_handling` defaults to `"keep"` and `case_handling` to `"lower_host"` for cross-project canonicalization consistency. If you set `host_encoding` (`"idna"` or `"unicode"`) to fold internationalized (IDN) hosts, that same value is also passed to the domain-filtering step so its comparisons stay consistent with the cleaned node keys. (Registrable-domain matching is encoding-independent, so this only matters if host-level filtering is involved.)
- self_loops
A character string specifying how to handle self-loops. Either "drop" (default) or "keep".
- drop_isolates_flag
Logical, whether to drop isolated nodes before PageRank computation. Defaults to TRUE.
- reverse
Logical. If `TRUE`, PageRank is computed on the transposed (edge-reversed) graph, yielding reverse / inverse PageRank instead of the usual inflow score. Default `FALSE`. See the "Reverse / inverse PageRank" section in Details for what it measures and which other arguments are compatible.
- weight_col
Optional name of a numeric column in `edge_list_df` containing edge weights. Higher weights make edges more likely to be followed. If `NULL` (default), all edges have equal weight.
- duplicate_edge_policy
How repeated `from -> to` rows are represented after URL cleaning, redirect/canonical folding, and domain filtering. One of:
- `"collapse"`
(default) Destination-level surfer: repeated rows collapse to one unweighted destination edge, preserving legacy `get_unique_edges()` behavior and the common binary PageRank convention.
- `"aggregate"`
Collapse each `from -> to` pair with [aggregate_edges()] semantics. Numeric columns, including `weight_col`, are summed; logical columns such as `nofollow` use the default `"any"` conflict policy.
- `"count_instances"`
Link-slot / edge-level surfer: repeated rows increase transition probability. With no `weight_col`, each surviving `from -> to` pair receives an internal weight equal to its duplicate-row count. With `weight_col`, weights are summed and an `instance_count` audit column is retained.
- nofollow_col
Optional name of a logical or 0/1 column in `edge_list_df` indicating nofollow edges. If `NULL` (default), no nofollow handling is performed.
- nofollow_action
How to handle nofollow edges when `nofollow_col` is provided. One of:
- `"evaporate"`
(default) Nofollow links remain outgoing slots: they consume their weighted share of the source node's outgoing PR budget but pass nothing to their targets. Implemented via a sink node that absorbs the unpropagated PR.
- `"drop"`
Remove nofollow edges before allocating the outgoing budget. They consume no slots, so followed edges divide the full budget among themselves.
- `"keep"`
Retain and follow these edges normally, so their targets receive their allocated shares.
- indexability_df
Optional data frame mapping URLs to their indexability status (e.g., from an SEO crawl export). See Details.
- indexability_url_col
Name of the URL column in `indexability_df`. Default `"url"`.
- indexability_status_col
Name of the status column in `indexability_df`. Default `"indexability_status"`. Values are comma-separated strings; recognized statuses are `"Blocked by robots.txt"` and `"noindex"` (case-insensitive for noindex).
- robots_blocked_action
How to present robots.txt-blocked pages in results. One of:
- `"trap"`
(default) Blocked pages appear in results showing their accumulated (trapped) PageRank, useful for seeing wasted PR.
- `"vanish"`
Blocked pages are removed from results. Their PR disappears.
- edge_from_col, edge_to_col
Names of from/to columns in `edge_list_df`.
- redirect_from_col, redirect_to_col
Names of from/to columns in `redirects_df`.
- duplicate_from_policy
How to handle conflicting redirects in `redirects_df`. Passed through to [resolve_redirects()]. Default `"strict"` (error on conflicts). See [resolve_redirects()] for all available policies.
- loop_handling
How to handle redirect cycles. Passed through to [resolve_redirects()]. Default `"error"`. See [resolve_redirects()] for all available policies.
- canonicals_df
An optional data frame of declared `rel=canonical` links, with `from`/`to` columns (or as set by `canonical_from_col` / `canonical_to_col`) pairing a source URL with the canonical it declares. Default `NULL` (opt-in; the default preserves current behavior). Canonicals are a **distinct, advisory** signal from enforced 3xx `redirects_df`: they are tracked separately and audited via [audit_canonicals()] / [audit_fold()], then folded into the same composed map as redirects (see [build_fold_map()]). Self-canonicals drop as no-ops.
- canonical_from_col, canonical_to_col
From/to columns in `canonicals_df`. Default `"from"` / `"to"`.
- clean_canonical_urls
Logical, whether to clean URLs in `canonicals_df` using the same resolved `rurl_params` profile as edge and redirect cleaning. Default `TRUE`. Only effective when `canonicals_df` is provided.
- canonical_duplicate_from_policy
How to handle a canonical source that declares multiple distinct canonicals. Reuses the `duplicate_from_policy` enum (see [resolve_redirects()]). Default `"strict"`.
- canonical_loop_handling
How to handle cycles among declared canonicals. Reuses the `loop_handling` enum. Default `"error"`.
- canonical_conflict_policy
How to resolve a redirect-vs-canonical disagreement on the **same source** URL. One of `"redirect_wins"` (default; the 3xx wins and the canonical on a redirecting source is ignored and flagged), `"error"` (error on genuine disagreement), or `"canonical_wins"` (the declared canonical wins for that source, still flagged). See [build_fold_map()].
- out_of_scope_fold
Policy for composed fold-map entries whose **target** (the representative a source folds onto) is not itself a crawled node. The crawled node set is the unique, non-`NA` edge endpoints captured immediately before folding (indexability URLs are not part of scope). Such an out-of-scope fold silently relabels a crawled page onto an uncrawled URL, inventing a phantom vertex (e.g. a staging crawl whose canonicals all point at the uncrawled production domain). One of:
- `"relabel"`
(Default) Apply the full fold map unchanged, relabeling crawled sources onto their out-of-scope targets. Preserves historical behavior.
- `"keep"`
Drop the out-of-scope entries from the fold map before applying it, so crawled source nodes retain their as-crawled identity. The same filtered map is applied to the TIPR prior fold, keeping edges and prior in one namespace.
- `"leak"`
Treat each such crawled source like an external redirect: route it onto a synthetic **leak sink** node (distinct from the nofollow sink) so the equity flowing INTO it leaves the measured graph ("these pages won't rank; equity goes elsewhere"). The source's own teleport prior is routed to the sink too. The evaporated equity is reported as **leaked mass** in the `mass` section of the `transition_audit` (`reported + sink + hidden + leaked = 1`). The leak sink is created whenever there is at least one out-of-scope fold, regardless of `nofollow_action`.
Regardless of policy, the count and list of out-of-scope folds (source, target, signal) are recorded in the `fold` section of the `transition_audit` object. See [transition_audit].
- keep_domains
Optional character vector of domains to keep. When provided, edges are filtered via [filter_links_by_domain()] so that only links where both endpoints belong to one of the specified domains are included. Useful for restricting to internal links. Default `NULL` (no domain filtering).
**Ordering:** filtering runs *after* redirect/canonical folding, so it scopes the post-fold (canonical) namespace, not the crawled input. If an out-of-scope canonical/redirect rewrites the crawled domain onto a different one, filtering on the crawled domain matches nothing (an empty graph). To scope the INPUT you crawled, run [filter_links_by_domain()] on the edge list *before* calling `pagerank()`.
- exclude_domains
Optional character vector of domains to exclude. Edges where either endpoint belongs to one of these domains are removed. Like `keep_domains`, this filters the post-fold namespace (see the ordering note above). Default `NULL` (no exclusion).
- keep_hosts
Optional character vector of exact hosts to keep (e.g. `"www.example.com"`), as opposed to registrable domains. Matched on the exact host using the same canonicalization profile as cleaning, so IDN folding (`host_encoding` in `rurl_params`) applies consistently. Default `NULL`.
- exclude_hosts
Optional character vector of exact hosts to exclude. Edges where either endpoint matches one of these hosts are removed. Ignore rules override keep rules. Default `NULL`.
- prior_df
Optional per-URL external-authority prior for TIPR (authority-weighted teleport). A data frame with one row per URL and a numeric weight. The prior URLs are canonicalized with the same `rurl_params` and folded through the same redirect map as the edges, weights for URLs that coalesce are summed, and the result is aligned to the final vertex set via [align_prior_to_vertices()] and passed to `igraph::page_rank(personalized = )`. Default `NULL` (uniform teleport).
The weight column must be an **additive raw count** — the redirect fold sums it (see `prior_weight_col`), which is only meaningful for quantities that add when URLs coalesce. This keeps the prior **source-agnostic**: the default is Ahrefs **referring domains**, but any backlink-source count is a drop-in swap (Ahrefs *links-to-target* or *dofollow-only referring domains*; SEMrush backlink/referring-domain counts; or even non-backlink counts such as GA4 entrances), simply by pointing `prior_weight_col` at it. Do **not** pass a calculated authority *score* (Ahrefs UR / DR, or any 0–100 rating): scores are not additive (folding two redirect variants is a `max`, not a `sum`), and a per-URL score like UR is itself a PageRank-style metric — using it as a teleport prior for PageRank is circular. See [align_prior_to_vertices()] for the full contract.
- prior_url_col, prior_weight_col
Column names in `prior_df`. Defaults `"url"` / `"weight"`. Swapping `prior_weight_col` between additive count columns is the supported way to A/B alternative authority metrics (e.g. via [pagerank_grid()]); see `prior_df` for which metrics qualify.
- prior_transform
How to shape raw authority before it becomes teleport mass. One of `"none"` (default, faithful linear share), `"log"`, `"percentile"`, `"minmax"`, `"zipf"`, `"rank_linear"`. See [transform_weights()]. Counts are summed on the raw scale before any transform.
- prior_alpha
Mixture weight in `[0, 1]` between uniform and authority-weighted teleport (`p = alpha * uniform + (1 - alpha) * authority_share`). `0` (default) is pure authority teleport; `1` reproduces uniform PageRank. See [align_prior_to_vertices()].
- prior_inject_unmatched
Logical. If `TRUE`, authoritative prior URLs that do not fold onto any existing vertex are added as edge-less isolate vertices so they appear in results carrying their teleport prior. Default `FALSE` (align-only: such URLs are dropped and logged).
- prior_verbose
Logical, whether to emit prior-alignment coverage diagnostics. Default `TRUE`. Only relevant when `prior_df` is supplied.
- damping
The PageRank damping factor \(\alpha\) (the random surfer's continue probability; the teleport probability is \(1 - \alpha\)). A single number in `[0, 1]`, default `0.85` — the field convention from Brin & Page. Forwarded to [compute_pagerank()] and on to `igraph::page_rank()`. Higher values weight the link structure more heavily but converge more slowly: a power-iteration solve needs roughly \(\log_{10}(\tau) / \log_{10}(\alpha)\) iterations to reach residual \(\tau\), so pushing \(\alpha\) toward 1 sharply raises the iteration count (raise `niter` accordingly when using the ARPACK solver). See the "Damping factor" section in Details for guidance on choosing it, and [damping_sensitivity()] to sweep a range of values.
- ...
Additional arguments passed to [compute_pagerank()] and subsequently to `igraph::page_rank()`. Besides `damping`, the recognized convergence controls `algo` (`"prpack"` / `"arpack"`), `eps`, and `niter` are forwarded here; see the "Convergence controls" section below.
Value
A data frame with node names and their PageRank scores. When nofollow evaporation, indexability handling, or `robots_blocked_action = "vanish"` is active, the returned scores may sum to less than 1. The difference is not undifferentiated "leakage": it is decomposed into **evaporated mass** (authority sent to the nofollow sink), **leaked mass** (authority sent to the leak sink under `out_of_scope_fold = "leak"`), and **hidden mass** (authority trapped on robots-blocked nodes removed from the results). The full breakdown — reported / evaporated (sink) / leaked / hidden / total (= 1) — is recorded in the `mass` field of the transition audit (see below).
The data frame additionally carries a `"transition_audit"` attribute (a [transition_audit] object) recording how the transition graph was built: row/edge counts, behavioral-weight coverage, normalization totals, the page-mass decomposition (reported / evaporated / leaked / hidden / total), dropped data (rows lost to NA / dedup / self-loops, unmatched prior URLs), and the model configuration used. Retrieve it with `attr(result, "transition_audit")`. This attribute is backward-compatible: the data frame itself (its columns and rows) is unchanged.
The result additionally carries a `"convergence"` attribute (a [pagerank_convergence] object); see the "Convergence controls" section.
Details
## Damping factor
The `damping` factor \(\alpha\) is the probability that the random surfer follows a link rather than teleporting; the remaining \(1 - \alpha\) is spread over the teleport vector (uniform, or the supplied TIPR `prior_df`).
The default `0.85` is the original Brin & Page value and remains the field convention, but it is *eminently empirical* — Boldi, Santini & Vigna (PageRank as a Function of the Damping Factor, WWW 2005) show it has no analytical claim to being uniquely correct. A common misconception is that values close to 1 yield "more accurate" rankings by trusting the link graph more; for real-world graphs they instead make the ranking dominated by the graph's largest near-cyclic component and, in the limit \(\alpha \to 1\), degenerate rather than converge to a more meaningful order.
Raising \(\alpha\) also degrades convergence sharply. A power-iteration solve needs about \(\log_{10}(\tau) / \log_{10}(\alpha)\) iterations to reach residual \(\tau\) (Langville & Meyer, Deeper Inside PageRank, Internet Mathematics 2004). At \(\tau = 10^{-8}\): \(\alpha = 0.85\) needs ~114 iterations, \(\alpha = 0.95\) ~362, and \(\alpha = 0.99\) ~1,833 — so a high damping factor is both slower and rarely better. When you do raise it on the ARPACK solver, raise `niter` to match (see "Convergence controls" below).
Both of those papers study the open web. Whether `0.85` is still the right convention for a site-scale intranet graph is an open empirical question; [damping_sensitivity()] sweeps a range of \(\alpha\) values so you can see how much the ranking on *your* graph actually moves.
## Convergence controls
`igraph::page_rank()` is called through one of two solver back-ends, selected with `algo` (forwarded via `...`):
- `"prpack"`
(default) A fast, exact direct solver. It has **no** tunable tolerance or iteration cap, and reports no iteration count.
- `"arpack"`
An iterative eigensolver that honors `eps` (the L1 tolerance) and `niter` (the maximum iterations), and reports how many iterations it used.
Modern `igraph` (2.x) removed the legacy `page_rank()` `eps` / `niter` arguments; this package re-exposes them as friendly aliases for the ARPACK `options$tol` / `options$maxiter` controls. Because PRPACK ignores them, supplying either `eps` or `niter` transparently switches `algo` to `"arpack"`. As a rule of thumb a power-iteration solve needs about `log10(eps) / log10(damping)` iterations, so raise `niter` when you push `damping` toward 1.
Every non-empty result carries a `"convergence"` attribute (a [pagerank_convergence] object) reporting the solver, iteration count (when the solver exposes it), and the solver-independent post-hoc L1 residual \(\|G x - x\|_1\) of the returned vector. Retrieve it with `attr(result, "convergence")`.
## Indexability handling
When `indexability_df` is provided, two types of pages receive special treatment:
**Indexed-corpus assumption and noindex pages:** `pagerankr` models the ranked corpus as the set of indexed documents. Under this package assumption, a noindex page is outside that corpus: it may receive authority through inlinks, but it cannot redistribute that authority within the indexed graph. Its outgoing links are therefore treated as nofollow for propagation and processed according to `nofollow_action`: `"evaporate"` leaves them as slot-consuming links whose shares reach the sink, `"drop"` removes them before shares are allocated, and `"keep"` follows them normally. This is a PageRank modeling choice in `pagerankr`; it does not assert that Google defines noindex as a nofollow directive. Noindex pages may still appear in the returned results so their received authority remains auditable. Hiding them would be an optional reporting choice, not a propagation correction.
**robots.txt-blocked pages:** Google cannot access the page content, so there are no visible outgoing links. All outgoing edges are removed and a self-loop is added to trap inbound PageRank. The `robots_blocked_action` parameter controls whether these pages appear in results (`"trap"`) or are removed (`"vanish"`).
**Priority rule:** robots.txt always takes precedence over noindex. If a page is both robots-blocked and noindex, it is treated as robots-blocked.
## Reverse / inverse PageRank (`reverse = TRUE`)
Standard PageRank measures **inflow** importance ("who points to me"). With `reverse = TRUE` the link graph is transposed before computation, yielding **outflow centrality** ("does this page funnel authority outward"). This is the *reverse PageRank* of Bar-Yossef & Mashiach (CIKM 2008), equivalent to the **CheiRank** of the transposed Google matrix, and the PageRank-flavored analogue of the *hub* score in Kleinberg's HITS. The sibling `semantic` project consumes this as an outflow signal.
Only edge orientation is flipped; URL cleaning, redirect folding, duplicate-edge policy, edge weights, domain/host filtering, and the teleport prior all behave identically (they are direction-agnostic). To obtain it directly from an edge list, swapping the from/to columns and running ordinary `pagerank()` is equivalent — `reverse = TRUE` just performs that flip internally so weight, redirect, and sink handling cannot be mis-wired by a manual swap.
**This is unrelated to the TIPR / personalized-prior feature (`prior_df`).** That seeds the *teleport* vector with external authority (e.g. backlinks) but still computes inflow PageRank on the forward graph; `reverse` is a pure *graph operation* on edge direction. The two are orthogonal and may be combined.
**Direction-sensitive features are rejected under `reverse = TRUE`** because their semantics do not transpose:
- `nofollow_action = "evaporate"`
Errors. The evaporation sink models a *source* wasting its outgoing budget; reversed, it would inject rank instead. Use `"drop"` — the correct treatment of a nofollowed link for outflow centrality, since it funnels no authority outward — or `"keep"`.
- `indexability_df`
Errors. noindex (outlinks-as-nofollow) and robots.txt blocking (drop outlinks + trap self-loop) encode forward crawl/index behavior with no meaningful transpose.
## Duplicate edge policy
The original PageRank papers define a page's vote as divided by its outgoing link count but do not pin down how repeated hyperlinks from one source page to the same target are represented. The standard textbook / binary operationalization treats the outgoing set as a destination relation, so multiple `A -> C` rows collapse to one destination edge. `pagerankr` keeps that as the default (`duplicate_edge_policy = "collapse"`) for backward compatibility and as the less spam-sensitive model.
Weighted / multigraph PageRank is also valid when repeated link slots are the intended unit. Use `duplicate_edge_policy = "count_instances"` for a link-slot surfer: `A -> B, A -> C, A -> C` sends twice as much outgoing mass to `C` as to `B`, equivalent to explicit weights `B = 1, C = 2` and to igraph's treatment of parallel edges. Use `"aggregate"` when duplicate rows should be collapsed loss-aware, especially with an existing `weight_col`; numeric duplicate weights are summed instead of silently keeping the first row.
## Fold-then-filter ordering (domain / host scope)
Redirect and canonical folding runs **before** the `keep_domains` / `exclude_domains` / `keep_hosts` / `exclude_hosts` filter. Folding can rewrite the node namespace: an out-of-scope canonical (e.g. every `staging.example.dev` page declaring a `example.com` canonical) relabels crawled nodes onto a domain you never crawled. Because the filter then sees only the post-fold (canonical) namespace, filtering on the domain you actually crawled matches nothing and returns an empty graph.
`pagerank()` detects this specific case – a filter value that classified one or more crawled (pre-fold) nodes but no surviving post-fold node – and emits an actionable `warning()` naming the folded-away value(s) and pointing at the out-of-scope fold as the cause. This is a diagnostic only; the fold-then-filter order is unchanged.
To scope the **input you crawled**, filter first: run [filter_links_by_domain()] on the edge list (and, if used, the redirect / canonical data frames) *before* calling `pagerank()`. To scope the folded graph, filter on the post-fold (canonical) domain/host instead.
Examples
# Basic example
edges <- data.frame(
from = c("http://A.com/", "B", "C?q=1", "D"),
to = c("B", "http://A.com", "D#frag", "D")
)
redirects <- data.frame(
from = c("C?q=1", "B"),
to = c("http://C_resolved.com", "A") # B redirects to A, C to C_resolved
)
# Run full pipeline
pr_full <- pagerank(
edges,
redirects_df = redirects, self_loops = "drop", drop_isolates_flag = TRUE
)
print(pr_full)
#> node_name pagerank
#> 1 A 0.41194645
#> 2 D#frag 0.11431514
#> 3 http://a.com/ 0.41194645
#> 4 http://c_resolved.com/ 0.06179197
# Run without URL cleaning for edges
# (warning expected if query params present)
pr_no_edge_clean <- pagerank(
edges,
redirects_df = redirects, clean_edge_urls = FALSE
)
#> Warning: URLs in `edge_list_df` may contain query parameters (e.g. '?' or '&'). Consider setting `clean_edge_urls = TRUE` for consistent PageRank calculation, using `rurl_params` to control `rurl::clean_url` behavior if needed.
print(pr_no_edge_clean)
#> node_name pagerank
#> 1 A 0.2236325
#> 2 D#frag 0.2236325
#> 3 http://A.com 0.3109701
#> 4 http://A.com/ 0.1208824
#> 5 http://c_resolved.com/ 0.1208824
# Keep isolates
edges_isol <- rbind(edges, data.frame(from = "ISO", to = "LAND"))
pr_keep_isolates <- pagerank(edges_isol, drop_isolates_flag = FALSE)
print(pr_keep_isolates)
#> node_name pagerank
#> 1 B 0.33277870
#> 2 C?q=1 0.04991681
#> 3 D 0.04991681
#> 4 D#frag 0.09234609
#> 5 ISO 0.04991681
#> 6 LAND 0.09234609
#> 7 http://a.com/ 0.33277870
# With nofollow edges (evaporate mode)
edges_nf <- data.frame(
from = c("A", "A", "B"), to = c("B", "C", "A"),
nofollow = c(FALSE, TRUE, FALSE)
)
pr_nf <- pagerank(edges_nf,
nofollow_col = "nofollow",
nofollow_action = "evaporate", clean_edge_urls = FALSE
)
print(pr_nf)
#> node_name pagerank
#> 1 A 0.1448141
#> 2 B 0.1115460
# Reverse / inverse PageRank (outflow centrality, a.k.a. CheiRank):
# a page that funnels authority outward scores high.
pr_reverse <- pagerank(edges, redirects_df = redirects, reverse = TRUE)
print(pr_reverse)
#> node_name pagerank
#> 1 A 0.41194645
#> 2 D#frag 0.06179197
#> 3 http://a.com/ 0.41194645
#> 4 http://c_resolved.com/ 0.11431514