Extract recipe details and main image from Okusno.je

Site images.24ur.comTask extract-okusno-je-recipeVersion v1Updated Jul 29, 2026Category recipes

Retrieve a recipe title, ingredients, preparation steps, and primary image from an Okusno.je recipe article, including its 24ur.com image CDN URL. This skill was captured from a live agent session on images.24ur.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Extract structured recipe information from the originating Okusno.je article and return its main image URL, which may be hosted on images.24ur.com.

When to Use

Use when the caller provides an Okusno.je recipe URL or otherwise identifies the originating recipe article and needs the title, ingredients, preparation procedure, and principal recipe photograph. The images.24ur.com URL alone is an image asset and does not contain the recipe metadata; do not attempt to infer the article from its opaque filename.

Workflow

  1. Navigate directly to {recipe-url} on okusno.je with waitUntil: domcontentloaded.
  2. In one page evaluation, dismiss button#didomi-notice-agree-button if present, then run this extractor:
(() => {
  const parse = (s) => {
    try {
      return JSON.parse(s);
    } catch {
      return null;
    }
  };
  const walk = (value) => {
    if (!value) return [];
    if (Array.isArray(value)) return value.flatMap(walk);
    if (typeof value === "object")
      return [value, ...Object.values(value).flatMap(walk)];
    return [];
  };
  const jsonLd = [...document.querySelectorAll('script[type="application/ld+json"]')]
    .map((s) => parse(s.textContent))
    .filter(Boolean);
  const recipe =
    walk(jsonLd).find((x) => {
      const t = x && x["@type"];
      return t === "Recipe" || (Array.isArray(t) && t.includes("Recipe"));
    }) || {};
  const text = (v) => (typeof v === "string" ? v.trim() : "");
  const ingredients = Array.isArray(recipe.recipeIngredient)
    ? recipe.recipeIngredient.map(text).filter(Boolean)
    : [
        ...document.querySelectorAll(
          '[itemprop="recipeIngredient"], .recipe-ingredients li, .ingredients li',
        ),
      ]
        .map((e) => e.textContent.trim())
        .filter(Boolean);
  const instructionText = (v) => {
    if (typeof v === "string") return v.trim();
    if (Array.isArray(v)) return v.map(instructionText).filter(Boolean).join("\n");
    if (v && typeof v === "object") return text(v.text || v.name);
    return "";
  };
  const procedure = Array.isArray(recipe.recipeInstructions)
    ? recipe.recipeInstructions.map(instructionText).filter(Boolean)
    : [instructionText(recipe.recipeInstructions)].filter(Boolean);
  const imageValue = recipe.image;
  const imageCandidates = Array.isArray(imageValue) ? imageValue : [imageValue];
  let mainImage =
    imageCandidates
      .map((x) => (typeof x === "string" ? x : x && (x.url || x.contentUrl)))
      .find(Boolean) || "";
  if (!mainImage) {
    const candidates = [...document.querySelectorAll("article img, main img, img")]
      .map((i) => ({
        url: i.currentSrc || i.src,
        area: (i.naturalWidth || 0) * (i.naturalHeight || 0),
      }))
      .filter((x) => x.url && x.area > 150000)
      .sort((a, b) => b.area - a.area);
    mainImage = candidates[0]?.url || "";
  }
  return {
    title:
      text(recipe.name) ||
      document.querySelector("h1")?.textContent.trim() ||
      document.title,
    ingredients,
    procedure,
    mainImage,
  };
})();

Site-Specific Gotchas

  • The recipe content is on okusno.je; images.24ur.com is the associated CDN and serves the photograph only.
  • Recipe metadata is normally exposed in application/ld+json as a Recipe object, potentially nested inside an @graph; search recursively rather than assuming the first JSON-LD script is the recipe.
  • The consent banner uses button#didomi-notice-agree-button; dismiss it only when present. The extractor otherwise reads the current page and makes no external requests.
  • Prefer recipe.image from JSON-LD because ordinary page image lists can include logos, thumbnails, advertisements, and related recipes. Use the large-image fallback only when structured image metadata is absent.
  • Never fabricate an article URL from an opaque CDN filename. If only the final image URL is available, return the image URL but report that the originating recipe page must be supplied separately.

Expected Output

Return an object with exactly these fields:

  • title: recipe title
  • ingredients: ordered array of ingredient strings
  • procedure: ordered array of preparation-step strings
  • mainImage: primary image URL, commonly an images.24ur.com URL

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=images.24ur.com&task=extract-okusno-je-recipe