Create a GET response to call the API
# Create GET request
foodbank <- httr::GET("https://www.givefood.org.uk/api/2/foodbanks/")
# View API GET response result
str(foodbank)
## List of 10
## $ url : chr "https://www.givefood.org.uk/api/2/foodbanks/"
## $ status_code: int 403
## $ headers :List of 22
## ..$ date : chr "Mon, 22 Sep 2025 22:06:06 GMT"
## ..$ content-type : chr "text/html; charset=UTF-8"
## ..$ accept-ch : chr "Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platfor"| __truncated__
## ..$ cf-mitigated : chr "challenge"
## ..$ critical-ch : chr "Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platfor"| __truncated__
## ..$ cross-origin-embedder-policy: chr "require-corp"
## ..$ cross-origin-opener-policy : chr "same-origin"
## ..$ cross-origin-resource-policy: chr "same-origin"
## ..$ origin-agent-cluster : chr "?1"
## ..$ permissions-policy : chr "accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),g"| __truncated__
## ..$ referrer-policy : chr "same-origin"
## ..$ server-timing : chr "chlray;desc=\"98351b882d0ec475\""
## ..$ x-content-type-options : chr "nosniff"
## ..$ x-frame-options : chr "SAMEORIGIN"
## ..$ cache-control : chr "private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
## ..$ expires : chr "Thu, 01 Jan 1970 00:00:01 GMT"
## ..$ vary : chr "Accept-Encoding"
## ..$ speculation-rules : chr "\"/cdn-cgi/speculation\""
## ..$ server : chr "cloudflare"
## ..$ cf-ray : chr "98351b882d0ec475-EWR"
## ..$ content-encoding : chr "gzip"
## ..$ alt-svc : chr "h3=\":443\"; ma=86400"
## ..- attr(*, "class")= chr [1:2] "insensitive" "list"
## $ all_headers:List of 1
## ..$ :List of 3
## .. ..$ status : int 403
## .. ..$ version: chr "HTTP/2"
## .. ..$ headers:List of 22
## .. .. ..$ date : chr "Mon, 22 Sep 2025 22:06:06 GMT"
## .. .. ..$ content-type : chr "text/html; charset=UTF-8"
## .. .. ..$ accept-ch : chr "Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platfor"| __truncated__
## .. .. ..$ cf-mitigated : chr "challenge"
## .. .. ..$ critical-ch : chr "Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platfor"| __truncated__
## .. .. ..$ cross-origin-embedder-policy: chr "require-corp"
## .. .. ..$ cross-origin-opener-policy : chr "same-origin"
## .. .. ..$ cross-origin-resource-policy: chr "same-origin"
## .. .. ..$ origin-agent-cluster : chr "?1"
## .. .. ..$ permissions-policy : chr "accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),g"| __truncated__
## .. .. ..$ referrer-policy : chr "same-origin"
## .. .. ..$ server-timing : chr "chlray;desc=\"98351b882d0ec475\""
## .. .. ..$ x-content-type-options : chr "nosniff"
## .. .. ..$ x-frame-options : chr "SAMEORIGIN"
## .. .. ..$ cache-control : chr "private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
## .. .. ..$ expires : chr "Thu, 01 Jan 1970 00:00:01 GMT"
## .. .. ..$ vary : chr "Accept-Encoding"
## .. .. ..$ speculation-rules : chr "\"/cdn-cgi/speculation\""
## .. .. ..$ server : chr "cloudflare"
## .. .. ..$ cf-ray : chr "98351b882d0ec475-EWR"
## .. .. ..$ content-encoding : chr "gzip"
## .. .. ..$ alt-svc : chr "h3=\":443\"; ma=86400"
## .. .. ..- attr(*, "class")= chr [1:2] "insensitive" "list"
## $ cookies :'data.frame': 0 obs. of 7 variables:
## ..$ domain : logi(0)
## ..$ flag : logi(0)
## ..$ path : logi(0)
## ..$ secure : logi(0)
## ..$ expiration: 'POSIXct' num(0)
## ..$ name : logi(0)
## ..$ value : logi(0)
## $ content : raw [1:7021] 3c 21 44 4f ...
## $ date : POSIXct[1:1], format: "2025-09-22 22:06:06"
## $ times : Named num [1:6] 0 0.000738 0.013335 0.032612 0.073649 ...
## ..- attr(*, "names")= chr [1:6] "redirect" "namelookup" "connect" "pretransfer" ...
## $ request :List of 7
## ..$ method : chr "GET"
## ..$ url : chr "https://www.givefood.org.uk/api/2/foodbanks/"
## ..$ headers : Named chr "application/json, text/xml, application/xml, */*"
## .. ..- attr(*, "names")= chr "Accept"
## ..$ fields : NULL
## ..$ options :List of 2
## .. ..$ useragent: chr "libcurl/8.11.1 r-curl/6.2.0 httr/1.4.7"
## .. ..$ httpget : logi TRUE
## ..$ auth_token: NULL
## ..$ output : list()
## .. ..- attr(*, "class")= chr [1:2] "write_memory" "write_function"
## ..- attr(*, "class")= chr "request"
## $ handle :Class 'curl_handle' <externalptr>
## - attr(*, "class")= chr "response"
# View the main source of the data needed (normally content)
str(foodbank$content)
## raw [1:7021] 3c 21 44 4f ...
Convert the raw content to text (JSON string)
foodbankcontent <- httr::content(foodbank, as="text")
## No encoding supplied: defaulting to UTF-8.
str(foodbankcontent)
## chr "<!DOCTYPE html><html lang=\"en-US\"><head><title>Just a moment...</title><meta http-equiv=\"Content-Type\" cont"| __truncated__
## chr "[\n {\n \"name\": \"Littlehampton & District Food Bank\",\n \"alt_name\": null,\n \"slug\": \"littleh"| __truncated__
Convert the JSON string to a dataframe and view as a table
# Load required packages
pacman::p_load(httr, jsonlite)
# Correct API URL (JSON endpoint for foodbanks)
url <- "https://www.givefood.org.uk/api/2/foodbanks/"
# Send GET request
foodbank <- httr::GET(url)
# Check the status code (200 means success)
status_code(foodbank)
## [1] 403
# If success, parse content as JSON
if (status_code(foodbank) == 200) {
foodbankcontent <- httr::content(foodbank, as = "text", encoding = "UTF-8")
foodbankJSON <- jsonlite::fromJSON(foodbankcontent, flatten = TRUE)
head(foodbankJSON)
} else {
print("API request failed. Check the URL or internet connection.")
}
## [1] "API request failed. Check the URL or internet connection."
#{r #setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
# Load necessary packages
if (!require(knitr)) install.packages("knitr")
## Loading required package: knitr
library(knitr)
answers <- data.frame(
Question = 1:10,
Answer = c(
"True", # Q1 - API benefits
"False", # Q2 - Don't need to re-install packages
"True", # Q3 - Must load library
"A, B, C, D", # Q4 - All sources valid
"True", # Q5 - getSymbols sources
"F", # Q6 - Only correct format & range
"86", # Q7 - Total trading days
"D", # Q8 - Highest Open during Dec 9–18
"True", # Q9 - DataCamp completion
"True" # Q10 - API extraction commitment
),
Explanation = c(
"APIs allow control over data exposure & rate limiting.",
"install.packages() is only needed once, not every session.",
"library() is required each session to access package functions.",
"All methods provide documentation or usage examples.",
"getSymbols supports multiple sources like Yahoo, FRED, CSV, etc.",
"getSymbols('MSFT', ..., to = '2025-01-31') is the exact match.",
"MSFT has 86 trading days between Oct 1 and Jan 31.",
"Highest open price occurred in Dec 9–18 period.",
"DataCamp R course completion or commitment is acknowledged.",
"Student is prepared to show custom API use not covered in class."
)
)
kable(answers, caption = "Quiz Answer Key with Justifications", align = "c")
Quiz Answer Key with Justifications
1 |
True |
APIs allow control over data exposure & rate
limiting. |
2 |
False |
install.packages() is only needed once, not every
session. |
3 |
True |
library() is required each session to access package
functions. |
4 |
A, B, C, D |
All methods provide documentation or usage
examples. |
5 |
True |
getSymbols supports multiple sources like Yahoo,
FRED, CSV, etc. |
6 |
F |
getSymbols(‘MSFT’, …, to = ‘2025-01-31’) is the exact
match. |
7 |
86 |
MSFT has 86 trading days between Oct 1 and Jan
31. |
8 |
D |
Highest open price occurred in Dec 9–18 period. |
9 |
True |
DataCamp R course completion or commitment is
acknowledged. |
10 |
True |
Student is prepared to show custom API use not
covered in class. |