Copying AMIs between accounts is difficult, because even if an image is public, the snapshot behind it is private by default. Here we’ll talk about ways of getting around it.
The easy way is to start an instance with the desired image, then create a new image  from the instance. We can then copy to another region  if we want to.
A more involved approach is to copy the snapshot(s) to our account and then register the image. This does require knowing who the owner of the image is in order for them to share the snapshots with us.
Discovery 
We’ll need to describe the image we want to copy to find the snapshot(s) that will need to be shared.
Example API Request 
1
2
3
4 https://ec2.us-east-1.amazonaws.com
?Action=DescribeImages
&ImageId.1=ami-12345678
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3 aws --region us-east-1 ec2 \ 
describe-images \ 
--image-ids "[ \" ami-12345678 \" ]" 
  
 
 
Output 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 { 
     "Images" :   [ 
         { 
             "VirtualizationType" :   "paravirtual" , 
             "Name" :   "Example_Image" , 
             "Hypervisor" :   "xen" , 
             "ImageId" :   "ami-12345678" , 
             "RootDeviceType" :   "ebs" , 
             "State" :   "available" , 
             "BlockDeviceMappings" :   [ 
                 { 
                     "DeviceName" :   "/dev/sda" , 
                     "Ebs" :   { 
                         "DeleteOnTermination" :   true , 
                         "SnapshotId" :   "snap-23456789" , 
                         "VolumeSize" :   10 , 
                         "VolumeType" :   "standard" , 
                         "Encrypted" :   false 
                     } 
                 }, 
                 { 
                     "DeviceName" :   "/dev/sdb" , 
                     "VirtualName" :   "ephemeral0" 
                 }, 
                 { 
                     "DeviceName" :   "/dev/sdc" , 
                     "VirtualName" :   "ephemeral1" 
                 }, 
                 { 
                     "DeviceName" :   "/dev/sdd" , 
                     "VirtualName" :   "ephemeral2" 
                 }, 
                 { 
                     "DeviceName" :   "/dev/sde" , 
                     "VirtualName" :   "ephemeral3" 
                 } 
             ], 
             "Architecture" :   "x86_64" , 
             "ImageLocation" :   "234567890123/Example_Image" , 
             "KernelId" :   "aki-b4aa75dd" , 
             "OwnerId" :   "234567890123" , 
             "RootDeviceName" :   "/dev/sda" , 
             "Public" :   true , 
             "ImageType" :   "machine" , 
             "Description" :   "Example Description" 
         } 
     ] 
 } 
 
 
 
Note all the snapshots in BlockDeviceMappings, just snap-23456789 in this case.
Sharing 
Looking at OwnerId of the image description, we’ll get account 234567890123 to share with us (account 123456789012).
With User 
You can have the other account share it with specified users.
Example API Request 
1
2
3
4
5 https://ec2.us-east-1.amazonaws.com
?Action=ModifySnapshotAttribute
&SnapshotId=snap-23456789
&CreateVolumePermission.Add.1.UserId=123456789012
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6
7
8
9
10 aws --profile "account2"  --region us-east-1 ec2 \ 
modify-snapshot-attribute \ 
--snapshot-id "snap-23456789"  \ 
--create-volume-permission "{
     \" Add \" : [
        {
             \" UserId \" :  \" 123456789012 \" 
        }
    ]
}" 
  
 
 
With Public 
Or the other account can just make the snapshot(s) public.
Example API Request 
1
2
3
4
5 https://ec2.us-east-1.amazonaws.com
?Action=ModifySnapshotAttribute
&SnapshotId=snap-23456789
&CreateVolumePermission.Add.1.Group=all
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6
7
8
9
10 aws --profile "account2"  --region us-east-1 ec2 \ 
modify-snapshot-attribute \ 
--snapshot-id "snap-23456789"  \ 
--create-volume-permission "{
     \" Add \" : [
        {
             \" Group \" :  \" all \" 
        }
    ]
}" 
  
 
 
Copy Snapshot 
Now we copy the snapshot(s).
Example API Request 
1
2
3
4
5
6
7 https://ec2.us-east-1.amazonaws.com
?Action=CopySnapshot
&SourceRegion=us-east-1
&SourceSnapshotId=snap-23456789
&DestinationRegion=us-east-1
&Description=Example&20Description
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6 aws --region us-east-1 ec2 \ 
copy-snapshot \ 
--source-region "us-east-1"  \ 
--source-snapshot-id "snap-23456789"  \ 
--destination-region "us-east-1"  \ 
--description "Example Description" 
  
 
 
Output 
1
2
3 { 
     "SnapshotId" :   "snap-abcdef01" 
 } 
 
 
 
Register Image 
And register the image once the snapshot(s) are copied.
Example API Request 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 https://ec2.us-east-1.amazonaws.com/
?Action=RegisterImage
&Name=Example_Image_Name
&Description=Example%20Image%20Description
&Architecture=x86_64
&KernelId=aki-b4aa75dd
&RootDeviceName=/dev/sda
&BlockDeviceMapping.1.DeviceName=/dev/sda1
&BlockDeviceMapping.1.SnapshotId=snap-abcdef01
&BlockDeviceMapping.2.DeviceName=/dev/sdb
&BlockDeviceMapping.2.VirtualName=ephemeral0
&BlockDeviceMapping.3.DeviceName=/dev/sdc
&BlockDeviceMapping.3.VirtualName=ephemeral1
&BlockDeviceMapping.4.DeviceName=/dev/sdd
&BlockDeviceMapping.4.VirtualName=ephemeral2
&BlockDeviceMapping.5.DeviceName=/dev/sde
&BlockDeviceMapping.5.VirtualName=ephemeral3
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 aws --region= us-east-1 ec2 \ 
register-image \ 
--name "Example_Image_Name"  \ 
--description "Example Image Description"  \ 
--architecture x86_64 \ 
--kernel-id aki-b4aa75dd \ 
--root-device-name "/dev/sda"  \ 
--block-device-mappings "[
    {
         \" DeviceName \" :  \" /dev/sda1 \" ,
         \" Ebs \" : {
             \" SnapshotId \" :  \" snap-abcdef01 \" 
        }
    },
    {
         \" DeviceName \" :  \" /dev/sdb \" ,
         \" VirtualName \" :  \" ephemeral0 \" 
    },
    {
         \" DeviceName \" :  \" /dev/sdc \" ,
         \" VirtualName \" :  \" ephemeral1 \" 
    },
    {
         \" DeviceName \" :  \" /dev/sdd \" ,
         \" VirtualName \" :  \" ephemeral2 \" 
    },
    {
         \" DeviceName \" :  \" /dev/sde \" ,
         \" VirtualName \" :  \" ephemeral3 \" 
    }
]" 
  
 
 
Output 
1
2
3 { 
     "ImageId" :   "ami-a1b2c3d4" 
 } 
 
 
 
Turn Off Sharing 
With User 
If the other account wants to revoke permission for a single user:
Example API Request 
1
2
3
4
5 https://ec2.us-east-1.amazonaws.com
?Action=ModifySnapshotAttribute
&SnapshotId=snap-23456789
&CreateVolumePermission.Remove.1.UserId=123456789012
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6
7
8
9
10 aws --profile "account2"  --region us-east-1 ec2 \ 
modify-snapshot-attribute \ 
--snapshot-id "snap-23456789"  \ 
--create-volume-permission "{
     \" Remove \" : [
        {
             \" UserId \" :  \" 123456789012 \" 
        }
    ]
}" 
  
 
 
With Public 
If the snapshot(s) were public and the other account now desires to have them be private again:
Example API Request 
1
2
3
4
5 https://ec2.us-east-1.amazonaws.com
?Action=ModifySnapshotAttribute
&SnapshotId=snap-23456789
&CreateVolumePermission.Remove.1.Group=all
&*AUTHPARAMS*
  
 
 
Console - user@hostname ~ $ 
1
2
3
4
5
6
7
8
9
10 aws --profile "account2"  --region us-east-1 ec2 \ 
modify-snapshot-attribute \ 
--snapshot-id "snap-23456789"  \ 
--create-volume-permission "{
     \" Remove \" : [
        {
             \" Group \" :  \" all \" 
        }
    ]
}"