Blog

Airtable Scripts: Loading and Accessing Linked Records

FE
Filla EditorialintermediateNov 22, 2025

Loading linked records in scripts

When you get a linked record field value, you only get an array with the record's name and ID—not the full record. To access fields from linked records, you need to load the record using selectRecordAsync().


The problem

When you retrieve a linked record field value, Airtable returns an array of objects containing only:

  • name: The primary field value
  • id: The record ID

You cannot directly access other fields from the linked record.

What doesn't work

let record = await input.recordAsync("Select a record", view)
let spouse = record.getCellValue("Spouse")

// This will NOT work - spouse is just an array with name and id
let spouseNation = spouse.getCellValueAsString("Nation of Birth") // ❌ Error!

Why it fails: spouse is an array like [{name: "Jane Doe", id: "rec123"}], not a record object.


The solution: selectRecordAsync()

To access fields from a linked record, you must load the full record using selectRecordAsync().

Basic pattern

// Get the linked record value (array with name and id)
let linkedRecordValue = record.getCellValue("Spouse")
let linkedRecordId = linkedRecordValue[0].id

// Load the full record
let linkedRecord = await table.selectRecordAsync(linkedRecordId)

// Now you can access fields
let nation = linkedRecord.getCellValueAsString("Nation of Birth") // ✅ Works!

Complete example

Scenario: Accessing spouse information

// Get the table
let table = base.getTable("Characters")
let view = table.getView("Living Males")

// Get a record from user input
let deadMansRecord = await input.recordAsync("Who Died", view)

// Get the linked record value (this is just an array)
let theWidow = deadMansRecord.getCellValue("Spouse")
let theWidowId = theWidow[0].id

// Load the full record
let widowRecord = await table.selectRecordAsync(theWidowId)

// Now access fields from the linked record
let widowHome = widowRecord.getCellValueAsString("Nation of Birth")
console.log(widowHome) // "Germany"

Handling multiple linked records

If a linked record field can contain multiple records, loop through them:

let linkedRecords = record.getCellValue("Team Members")

if (linkedRecords && linkedRecords.length > 0) {
  for (let linkedRecord of linkedRecords) {
    // Load each full record
    let fullRecord = await table.selectRecordAsync(linkedRecord.id)

    // Access fields
    let email = fullRecord.getCellValueAsString("Email")
    console.log(email)
  }
}

Loading records from different tables

If the linked record is in a different table, get that table first:

// Current table
let currentTable = base.getTable("Tasks")

// Get linked record from different table
let projectLink = record.getCellValue("Project")
let projectId = projectLink[0].id

// Get the target table
let projectsTable = base.getTable("Projects")

// Load the record from the different table
let projectRecord = await projectsTable.selectRecordAsync(projectId)

// Access fields
let projectName = projectRecord.getCellValueAsString("Name")
let budget = projectRecord.getCellValue("Budget")

Common patterns

Pattern 1: Single linked record

let linkedValue = record.getCellValue("Linked Field")
if (linkedValue && linkedValue.length > 0) {
  let linkedRecord = await table.selectRecordAsync(linkedValue[0].id)
  let fieldValue = linkedRecord.getCellValue("Field Name")
}

Pattern 2: Multiple linked records

let linkedValues = record.getCellValue("Linked Field")
if (linkedValues && linkedValues.length > 0) {
  for (let link of linkedValues) {
    let linkedRecord = await table.selectRecordAsync(link.id)
    let fieldValue = linkedRecord.getCellValue("Field Name")
    // Process each record
  }
}

Pattern 3: Chained linked records (lookup of lookup)

// First level
let task = await input.recordAsync("Select task", view)
let projectLink = task.getCellValue("Project")
let projectId = projectLink[0].id

// Load project
let project = await projectsTable.selectRecordAsync(projectId)

// Second level - get client from project
let clientLink = project.getCellValue("Client")
let clientId = clientLink[0].id

// Load client
let client = await clientsTable.selectRecordAsync(clientId)

// Access client fields
let clientEmail = client.getCellValueAsString("Email")

Performance tips

Load only what you need

Specify which fields you need when loading records:

let linkedRecord = await table.selectRecordAsync(recordId, {
  fields: ["Name", "Email", "Status"], // Only load these fields
})

This is more efficient than loading all fields.

Batch operations

If you need to load many linked records, consider batching:

let linkedValues = record.getCellValue("Team Members")
let recordIds = linkedValues.map((link) => link.id)

// Load all at once (if supported in your use case)
// Or process in batches to avoid timeouts

Error handling

Always check if linked records exist before accessing them:

let linkedValue = record.getCellValue("Spouse")

if (!linkedValue || linkedValue.length === 0) {
  console.log("No linked record found")
  return
}

try {
  let linkedRecord = await table.selectRecordAsync(linkedValue[0].id)
  let value = linkedRecord.getCellValue("Field")
} catch (error) {
  console.error("Error loading record:", error)
}

What you get from getCellValue()

When you call getCellValue() on a linked record field, you get:

;[
  {
    name: "Record Name", // Primary field value
    id: "recXXXXXXXXXXXX", // Record ID
  },
]

You cannot:

  • Access other fields directly
  • Call getCellValue() on this array
  • Use it as a record object

You must:

  • Extract the id
  • Use selectRecordAsync() to load the full record
  • Then access fields from the loaded record

Common mistakes

Mistake 1: Trying to access fields directly

// ❌ Wrong
let spouse = record.getCellValue("Spouse")
let email = spouse.getCellValue("Email") // Error!

Fix:

// ✅ Correct
let spouse = record.getCellValue("Spouse")
let spouseRecord = await table.selectRecordAsync(spouse[0].id)
let email = spouseRecord.getCellValue("Email")

Mistake 2: Not checking if linked record exists

// ❌ Wrong - will error if no linked record
let spouse = record.getCellValue("Spouse")
let spouseRecord = await table.selectRecordAsync(spouse[0].id)

Fix:

// ✅ Correct
let spouse = record.getCellValue("Spouse")
if (spouse && spouse.length > 0) {
  let spouseRecord = await table.selectRecordAsync(spouse[0].id)
}

Mistake 3: Using wrong table

// ❌ Wrong - using current table for different table's record
let projectLink = record.getCellValue("Project")
let projectRecord = await currentTable.selectRecordAsync(projectLink[0].id)

Fix:

// ✅ Correct - get the correct table
let projectsTable = base.getTable("Projects")
let projectLink = record.getCellValue("Project")
let projectRecord = await projectsTable.selectRecordAsync(projectLink[0].id)

Quick reference

Task Code
Get linked record value record.getCellValue("Linked Field")
Extract record ID linkedValue[0].id
Load full record (same table) await table.selectRecordAsync(recordId)
Load full record (different table) await otherTable.selectRecordAsync(recordId)
Access field from loaded record loadedRecord.getCellValue("Field")
Check if linked record exists if (linkedValue && linkedValue.length > 0)

Complete working example

// Setup
let table = base.getTable("Characters")
let view = table.getView("Living Males")

// Get record from user
let record = await input.recordAsync("Select a character", view)

// Get linked spouse
let spouseLink = record.getCellValue("Spouse")

// Check if spouse exists
if (!spouseLink || spouseLink.length === 0) {
  output.text("No spouse linked")
} else {
  // Load the spouse record
  let spouseId = spouseLink[0].id
  let spouseRecord = await table.selectRecordAsync(spouseId)

  // Access spouse fields
  let spouseName = spouseRecord.getCellValueAsString("Name")
  let spouseNation = spouseRecord.getCellValueAsString("Nation of Birth")
  let spouseAge = spouseRecord.getCellValue("Age")

  // Display results
  output.text(`Spouse: ${spouseName}`)
  output.text(`Nation: ${spouseNation}`)
  output.text(`Age: ${spouseAge}`)
}

Tips

  • Always use selectRecordAsync() to load linked records before accessing fields
  • Check for existence before accessing linked records
  • Get the correct table when linked records are in different tables
  • Specify fields when loading to improve performance
  • Handle errors with try-catch blocks
  • Remember: Linked record values are arrays, not record objects

References

Community discussion on loading linked records: 'Loading' a record

Airtable Scripts: Loading and Accessing Linked Records